Home | History | Annotate | Download | only in mips
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <limits.h>  // For LONG_MIN, LONG_MAX.
      6 
      7 #include "src/v8.h"
      8 
      9 #if V8_TARGET_ARCH_MIPS
     10 
     11 #include "src/bootstrapper.h"
     12 #include "src/codegen.h"
     13 #include "src/cpu-profiler.h"
     14 #include "src/debug.h"
     15 #include "src/isolate-inl.h"
     16 #include "src/runtime.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 
     21 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
     22     : Assembler(arg_isolate, buffer, size),
     23       generating_stub_(false),
     24       has_frame_(false) {
     25   if (isolate() != NULL) {
     26     code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
     27                                   isolate());
     28   }
     29 }
     30 
     31 
     32 void MacroAssembler::Load(Register dst,
     33                           const MemOperand& src,
     34                           Representation r) {
     35   ASSERT(!r.IsDouble());
     36   if (r.IsInteger8()) {
     37     lb(dst, src);
     38   } else if (r.IsUInteger8()) {
     39     lbu(dst, src);
     40   } else if (r.IsInteger16()) {
     41     lh(dst, src);
     42   } else if (r.IsUInteger16()) {
     43     lhu(dst, src);
     44   } else {
     45     lw(dst, src);
     46   }
     47 }
     48 
     49 
     50 void MacroAssembler::Store(Register src,
     51                            const MemOperand& dst,
     52                            Representation r) {
     53   ASSERT(!r.IsDouble());
     54   if (r.IsInteger8() || r.IsUInteger8()) {
     55     sb(src, dst);
     56   } else if (r.IsInteger16() || r.IsUInteger16()) {
     57     sh(src, dst);
     58   } else {
     59     if (r.IsHeapObject()) {
     60       AssertNotSmi(src);
     61     } else if (r.IsSmi()) {
     62       AssertSmi(src);
     63     }
     64     sw(src, dst);
     65   }
     66 }
     67 
     68 
     69 void MacroAssembler::LoadRoot(Register destination,
     70                               Heap::RootListIndex index) {
     71   lw(destination, MemOperand(s6, index << kPointerSizeLog2));
     72 }
     73 
     74 
     75 void MacroAssembler::LoadRoot(Register destination,
     76                               Heap::RootListIndex index,
     77                               Condition cond,
     78                               Register src1, const Operand& src2) {
     79   Branch(2, NegateCondition(cond), src1, src2);
     80   lw(destination, MemOperand(s6, index << kPointerSizeLog2));
     81 }
     82 
     83 
     84 void MacroAssembler::StoreRoot(Register source,
     85                                Heap::RootListIndex index) {
     86   sw(source, MemOperand(s6, index << kPointerSizeLog2));
     87 }
     88 
     89 
     90 void MacroAssembler::StoreRoot(Register source,
     91                                Heap::RootListIndex index,
     92                                Condition cond,
     93                                Register src1, const Operand& src2) {
     94   Branch(2, NegateCondition(cond), src1, src2);
     95   sw(source, MemOperand(s6, index << kPointerSizeLog2));
     96 }
     97 
     98 
     99 // Push and pop all registers that can hold pointers.
    100 void MacroAssembler::PushSafepointRegisters() {
    101   // Safepoints expect a block of kNumSafepointRegisters values on the
    102   // stack, so adjust the stack for unsaved registers.
    103   const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
    104   ASSERT(num_unsaved >= 0);
    105   if (num_unsaved > 0) {
    106     Subu(sp, sp, Operand(num_unsaved * kPointerSize));
    107   }
    108   MultiPush(kSafepointSavedRegisters);
    109 }
    110 
    111 
    112 void MacroAssembler::PopSafepointRegisters() {
    113   const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
    114   MultiPop(kSafepointSavedRegisters);
    115   if (num_unsaved > 0) {
    116     Addu(sp, sp, Operand(num_unsaved * kPointerSize));
    117   }
    118 }
    119 
    120 
    121 void MacroAssembler::PushSafepointRegistersAndDoubles() {
    122   PushSafepointRegisters();
    123   Subu(sp, sp, Operand(FPURegister::NumAllocatableRegisters() * kDoubleSize));
    124   for (int i = 0; i < FPURegister::NumAllocatableRegisters(); i+=2) {
    125     FPURegister reg = FPURegister::FromAllocationIndex(i);
    126     sdc1(reg, MemOperand(sp, i * kDoubleSize));
    127   }
    128 }
    129 
    130 
    131 void MacroAssembler::PopSafepointRegistersAndDoubles() {
    132   for (int i = 0; i < FPURegister::NumAllocatableRegisters(); i+=2) {
    133     FPURegister reg = FPURegister::FromAllocationIndex(i);
    134     ldc1(reg, MemOperand(sp, i * kDoubleSize));
    135   }
    136   Addu(sp, sp, Operand(FPURegister::NumAllocatableRegisters() * kDoubleSize));
    137   PopSafepointRegisters();
    138 }
    139 
    140 
    141 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src,
    142                                                              Register dst) {
    143   sw(src, SafepointRegistersAndDoublesSlot(dst));
    144 }
    145 
    146 
    147 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
    148   sw(src, SafepointRegisterSlot(dst));
    149 }
    150 
    151 
    152 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
    153   lw(dst, SafepointRegisterSlot(src));
    154 }
    155 
    156 
    157 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
    158   // The registers are pushed starting with the highest encoding,
    159   // which means that lowest encodings are closest to the stack pointer.
    160   return kSafepointRegisterStackIndexMap[reg_code];
    161 }
    162 
    163 
    164 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
    165   return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
    166 }
    167 
    168 
    169 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
    170   UNIMPLEMENTED_MIPS();
    171   // General purpose registers are pushed last on the stack.
    172   int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize;
    173   int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
    174   return MemOperand(sp, doubles_size + register_offset);
    175 }
    176 
    177 
    178 void MacroAssembler::InNewSpace(Register object,
    179                                 Register scratch,
    180                                 Condition cc,
    181                                 Label* branch) {
    182   ASSERT(cc == eq || cc == ne);
    183   And(scratch, object, Operand(ExternalReference::new_space_mask(isolate())));
    184   Branch(branch, cc, scratch,
    185          Operand(ExternalReference::new_space_start(isolate())));
    186 }
    187 
    188 
    189 void MacroAssembler::RecordWriteField(
    190     Register object,
    191     int offset,
    192     Register value,
    193     Register dst,
    194     RAStatus ra_status,
    195     SaveFPRegsMode save_fp,
    196     RememberedSetAction remembered_set_action,
    197     SmiCheck smi_check,
    198     PointersToHereCheck pointers_to_here_check_for_value) {
    199   ASSERT(!AreAliased(value, dst, t8, object));
    200   // First, check if a write barrier is even needed. The tests below
    201   // catch stores of Smis.
    202   Label done;
    203 
    204   // Skip barrier if writing a smi.
    205   if (smi_check == INLINE_SMI_CHECK) {
    206     JumpIfSmi(value, &done);
    207   }
    208 
    209   // Although the object register is tagged, the offset is relative to the start
    210   // of the object, so so offset must be a multiple of kPointerSize.
    211   ASSERT(IsAligned(offset, kPointerSize));
    212 
    213   Addu(dst, object, Operand(offset - kHeapObjectTag));
    214   if (emit_debug_code()) {
    215     Label ok;
    216     And(t8, dst, Operand((1 << kPointerSizeLog2) - 1));
    217     Branch(&ok, eq, t8, Operand(zero_reg));
    218     stop("Unaligned cell in write barrier");
    219     bind(&ok);
    220   }
    221 
    222   RecordWrite(object,
    223               dst,
    224               value,
    225               ra_status,
    226               save_fp,
    227               remembered_set_action,
    228               OMIT_SMI_CHECK,
    229               pointers_to_here_check_for_value);
    230 
    231   bind(&done);
    232 
    233   // Clobber clobbered input registers when running with the debug-code flag
    234   // turned on to provoke errors.
    235   if (emit_debug_code()) {
    236     li(value, Operand(BitCast<int32_t>(kZapValue + 4)));
    237     li(dst, Operand(BitCast<int32_t>(kZapValue + 8)));
    238   }
    239 }
    240 
    241 
    242 // Will clobber 4 registers: object, map, dst, ip.  The
    243 // register 'object' contains a heap object pointer.
    244 void MacroAssembler::RecordWriteForMap(Register object,
    245                                        Register map,
    246                                        Register dst,
    247                                        RAStatus ra_status,
    248                                        SaveFPRegsMode fp_mode) {
    249   if (emit_debug_code()) {
    250     ASSERT(!dst.is(at));
    251     lw(dst, FieldMemOperand(map, HeapObject::kMapOffset));
    252     Check(eq,
    253           kWrongAddressOrValuePassedToRecordWrite,
    254           dst,
    255           Operand(isolate()->factory()->meta_map()));
    256   }
    257 
    258   if (!FLAG_incremental_marking) {
    259     return;
    260   }
    261 
    262   // Count number of write barriers in generated code.
    263   isolate()->counters()->write_barriers_static()->Increment();
    264   // TODO(mstarzinger): Dynamic counter missing.
    265 
    266   if (emit_debug_code()) {
    267     lw(at, FieldMemOperand(object, HeapObject::kMapOffset));
    268     Check(eq,
    269           kWrongAddressOrValuePassedToRecordWrite,
    270           map,
    271           Operand(at));
    272   }
    273 
    274   Label done;
    275 
    276   // A single check of the map's pages interesting flag suffices, since it is
    277   // only set during incremental collection, and then it's also guaranteed that
    278   // the from object's page's interesting flag is also set.  This optimization
    279   // relies on the fact that maps can never be in new space.
    280   CheckPageFlag(map,
    281                 map,  // Used as scratch.
    282                 MemoryChunk::kPointersToHereAreInterestingMask,
    283                 eq,
    284                 &done);
    285 
    286   Addu(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag));
    287   if (emit_debug_code()) {
    288     Label ok;
    289     And(at, dst, Operand((1 << kPointerSizeLog2) - 1));
    290     Branch(&ok, eq, at, Operand(zero_reg));
    291     stop("Unaligned cell in write barrier");
    292     bind(&ok);
    293   }
    294 
    295   // Record the actual write.
    296   if (ra_status == kRAHasNotBeenSaved) {
    297     push(ra);
    298   }
    299   RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
    300                        fp_mode);
    301   CallStub(&stub);
    302   if (ra_status == kRAHasNotBeenSaved) {
    303     pop(ra);
    304   }
    305 
    306   bind(&done);
    307 
    308   // Clobber clobbered registers when running with the debug-code flag
    309   // turned on to provoke errors.
    310   if (emit_debug_code()) {
    311     li(dst, Operand(BitCast<int32_t>(kZapValue + 12)));
    312     li(map, Operand(BitCast<int32_t>(kZapValue + 16)));
    313   }
    314 }
    315 
    316 
    317 // Will clobber 4 registers: object, address, scratch, ip.  The
    318 // register 'object' contains a heap object pointer.  The heap object
    319 // tag is shifted away.
    320 void MacroAssembler::RecordWrite(
    321     Register object,
    322     Register address,
    323     Register value,
    324     RAStatus ra_status,
    325     SaveFPRegsMode fp_mode,
    326     RememberedSetAction remembered_set_action,
    327     SmiCheck smi_check,
    328     PointersToHereCheck pointers_to_here_check_for_value) {
    329   ASSERT(!AreAliased(object, address, value, t8));
    330   ASSERT(!AreAliased(object, address, value, t9));
    331 
    332   if (emit_debug_code()) {
    333     lw(at, MemOperand(address));
    334     Assert(
    335         eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value));
    336   }
    337 
    338   if (remembered_set_action == OMIT_REMEMBERED_SET &&
    339       !FLAG_incremental_marking) {
    340     return;
    341   }
    342 
    343   // Count number of write barriers in generated code.
    344   isolate()->counters()->write_barriers_static()->Increment();
    345   // TODO(mstarzinger): Dynamic counter missing.
    346 
    347   // First, check if a write barrier is even needed. The tests below
    348   // catch stores of smis and stores into the young generation.
    349   Label done;
    350 
    351   if (smi_check == INLINE_SMI_CHECK) {
    352     ASSERT_EQ(0, kSmiTag);
    353     JumpIfSmi(value, &done);
    354   }
    355 
    356   if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
    357     CheckPageFlag(value,
    358                   value,  // Used as scratch.
    359                   MemoryChunk::kPointersToHereAreInterestingMask,
    360                   eq,
    361                   &done);
    362   }
    363   CheckPageFlag(object,
    364                 value,  // Used as scratch.
    365                 MemoryChunk::kPointersFromHereAreInterestingMask,
    366                 eq,
    367                 &done);
    368 
    369   // Record the actual write.
    370   if (ra_status == kRAHasNotBeenSaved) {
    371     push(ra);
    372   }
    373   RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
    374                        fp_mode);
    375   CallStub(&stub);
    376   if (ra_status == kRAHasNotBeenSaved) {
    377     pop(ra);
    378   }
    379 
    380   bind(&done);
    381 
    382   // Clobber clobbered registers when running with the debug-code flag
    383   // turned on to provoke errors.
    384   if (emit_debug_code()) {
    385     li(address, Operand(BitCast<int32_t>(kZapValue + 12)));
    386     li(value, Operand(BitCast<int32_t>(kZapValue + 16)));
    387   }
    388 }
    389 
    390 
    391 void MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
    392                                          Register address,
    393                                          Register scratch,
    394                                          SaveFPRegsMode fp_mode,
    395                                          RememberedSetFinalAction and_then) {
    396   Label done;
    397   if (emit_debug_code()) {
    398     Label ok;
    399     JumpIfNotInNewSpace(object, scratch, &ok);
    400     stop("Remembered set pointer is in new space");
    401     bind(&ok);
    402   }
    403   // Load store buffer top.
    404   ExternalReference store_buffer =
    405       ExternalReference::store_buffer_top(isolate());
    406   li(t8, Operand(store_buffer));
    407   lw(scratch, MemOperand(t8));
    408   // Store pointer to buffer and increment buffer top.
    409   sw(address, MemOperand(scratch));
    410   Addu(scratch, scratch, kPointerSize);
    411   // Write back new top of buffer.
    412   sw(scratch, MemOperand(t8));
    413   // Call stub on end of buffer.
    414   // Check for end of buffer.
    415   And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit));
    416   if (and_then == kFallThroughAtEnd) {
    417     Branch(&done, eq, t8, Operand(zero_reg));
    418   } else {
    419     ASSERT(and_then == kReturnAtEnd);
    420     Ret(eq, t8, Operand(zero_reg));
    421   }
    422   push(ra);
    423   StoreBufferOverflowStub store_buffer_overflow =
    424       StoreBufferOverflowStub(isolate(), fp_mode);
    425   CallStub(&store_buffer_overflow);
    426   pop(ra);
    427   bind(&done);
    428   if (and_then == kReturnAtEnd) {
    429     Ret();
    430   }
    431 }
    432 
    433 
    434 // -----------------------------------------------------------------------------
    435 // Allocation support.
    436 
    437 
    438 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
    439                                             Register scratch,
    440                                             Label* miss) {
    441   Label same_contexts;
    442 
    443   ASSERT(!holder_reg.is(scratch));
    444   ASSERT(!holder_reg.is(at));
    445   ASSERT(!scratch.is(at));
    446 
    447   // Load current lexical context from the stack frame.
    448   lw(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
    449   // In debug mode, make sure the lexical context is set.
    450 #ifdef DEBUG
    451   Check(ne, kWeShouldNotHaveAnEmptyLexicalContext,
    452       scratch, Operand(zero_reg));
    453 #endif
    454 
    455   // Load the native context of the current context.
    456   int offset =
    457       Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
    458   lw(scratch, FieldMemOperand(scratch, offset));
    459   lw(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
    460 
    461   // Check the context is a native context.
    462   if (emit_debug_code()) {
    463     push(holder_reg);  // Temporarily save holder on the stack.
    464     // Read the first word and compare to the native_context_map.
    465     lw(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
    466     LoadRoot(at, Heap::kNativeContextMapRootIndex);
    467     Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
    468           holder_reg, Operand(at));
    469     pop(holder_reg);  // Restore holder.
    470   }
    471 
    472   // Check if both contexts are the same.
    473   lw(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
    474   Branch(&same_contexts, eq, scratch, Operand(at));
    475 
    476   // Check the context is a native context.
    477   if (emit_debug_code()) {
    478     push(holder_reg);  // Temporarily save holder on the stack.
    479     mov(holder_reg, at);  // Move at to its holding place.
    480     LoadRoot(at, Heap::kNullValueRootIndex);
    481     Check(ne, kJSGlobalProxyContextShouldNotBeNull,
    482           holder_reg, Operand(at));
    483 
    484     lw(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
    485     LoadRoot(at, Heap::kNativeContextMapRootIndex);
    486     Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
    487           holder_reg, Operand(at));
    488     // Restore at is not needed. at is reloaded below.
    489     pop(holder_reg);  // Restore holder.
    490     // Restore at to holder's context.
    491     lw(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
    492   }
    493 
    494   // Check that the security token in the calling global object is
    495   // compatible with the security token in the receiving global
    496   // object.
    497   int token_offset = Context::kHeaderSize +
    498                      Context::SECURITY_TOKEN_INDEX * kPointerSize;
    499 
    500   lw(scratch, FieldMemOperand(scratch, token_offset));
    501   lw(at, FieldMemOperand(at, token_offset));
    502   Branch(miss, ne, scratch, Operand(at));
    503 
    504   bind(&same_contexts);
    505 }
    506 
    507 
    508 void MacroAssembler::GetNumberHash(Register reg0, Register scratch) {
    509   // First of all we assign the hash seed to scratch.
    510   LoadRoot(scratch, Heap::kHashSeedRootIndex);
    511   SmiUntag(scratch);
    512 
    513   // Xor original key with a seed.
    514   xor_(reg0, reg0, scratch);
    515 
    516   // Compute the hash code from the untagged key.  This must be kept in sync
    517   // with ComputeIntegerHash in utils.h.
    518   //
    519   // hash = ~hash + (hash << 15);
    520   nor(scratch, reg0, zero_reg);
    521   sll(at, reg0, 15);
    522   addu(reg0, scratch, at);
    523 
    524   // hash = hash ^ (hash >> 12);
    525   srl(at, reg0, 12);
    526   xor_(reg0, reg0, at);
    527 
    528   // hash = hash + (hash << 2);
    529   sll(at, reg0, 2);
    530   addu(reg0, reg0, at);
    531 
    532   // hash = hash ^ (hash >> 4);
    533   srl(at, reg0, 4);
    534   xor_(reg0, reg0, at);
    535 
    536   // hash = hash * 2057;
    537   sll(scratch, reg0, 11);
    538   sll(at, reg0, 3);
    539   addu(reg0, reg0, at);
    540   addu(reg0, reg0, scratch);
    541 
    542   // hash = hash ^ (hash >> 16);
    543   srl(at, reg0, 16);
    544   xor_(reg0, reg0, at);
    545 }
    546 
    547 
    548 void MacroAssembler::LoadFromNumberDictionary(Label* miss,
    549                                               Register elements,
    550                                               Register key,
    551                                               Register result,
    552                                               Register reg0,
    553                                               Register reg1,
    554                                               Register reg2) {
    555   // Register use:
    556   //
    557   // elements - holds the slow-case elements of the receiver on entry.
    558   //            Unchanged unless 'result' is the same register.
    559   //
    560   // key      - holds the smi key on entry.
    561   //            Unchanged unless 'result' is the same register.
    562   //
    563   //
    564   // result   - holds the result on exit if the load succeeded.
    565   //            Allowed to be the same as 'key' or 'result'.
    566   //            Unchanged on bailout so 'key' or 'result' can be used
    567   //            in further computation.
    568   //
    569   // Scratch registers:
    570   //
    571   // reg0 - holds the untagged key on entry and holds the hash once computed.
    572   //
    573   // reg1 - Used to hold the capacity mask of the dictionary.
    574   //
    575   // reg2 - Used for the index into the dictionary.
    576   // at   - Temporary (avoid MacroAssembler instructions also using 'at').
    577   Label done;
    578 
    579   GetNumberHash(reg0, reg1);
    580 
    581   // Compute the capacity mask.
    582   lw(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset));
    583   sra(reg1, reg1, kSmiTagSize);
    584   Subu(reg1, reg1, Operand(1));
    585 
    586   // Generate an unrolled loop that performs a few probes before giving up.
    587   for (int i = 0; i < kNumberDictionaryProbes; i++) {
    588     // Use reg2 for index calculations and keep the hash intact in reg0.
    589     mov(reg2, reg0);
    590     // Compute the masked index: (hash + i + i * i) & mask.
    591     if (i > 0) {
    592       Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i)));
    593     }
    594     and_(reg2, reg2, reg1);
    595 
    596     // Scale the index by multiplying by the element size.
    597     ASSERT(SeededNumberDictionary::kEntrySize == 3);
    598     sll(at, reg2, 1);  // 2x.
    599     addu(reg2, reg2, at);  // reg2 = reg2 * 3.
    600 
    601     // Check if the key is identical to the name.
    602     sll(at, reg2, kPointerSizeLog2);
    603     addu(reg2, elements, at);
    604 
    605     lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset));
    606     if (i != kNumberDictionaryProbes - 1) {
    607       Branch(&done, eq, key, Operand(at));
    608     } else {
    609       Branch(miss, ne, key, Operand(at));
    610     }
    611   }
    612 
    613   bind(&done);
    614   // Check that the value is a normal property.
    615   // reg2: elements + (index * kPointerSize).
    616   const int kDetailsOffset =
    617       SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
    618   lw(reg1, FieldMemOperand(reg2, kDetailsOffset));
    619   And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
    620   Branch(miss, ne, at, Operand(zero_reg));
    621 
    622   // Get the value at the masked, scaled index and return.
    623   const int kValueOffset =
    624       SeededNumberDictionary::kElementsStartOffset + kPointerSize;
    625   lw(result, FieldMemOperand(reg2, kValueOffset));
    626 }
    627 
    628 
    629 // ---------------------------------------------------------------------------
    630 // Instruction macros.
    631 
    632 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) {
    633   if (rt.is_reg()) {
    634     addu(rd, rs, rt.rm());
    635   } else {
    636     if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
    637       addiu(rd, rs, rt.imm32_);
    638     } else {
    639       // li handles the relocation.
    640       ASSERT(!rs.is(at));
    641       li(at, rt);
    642       addu(rd, rs, at);
    643     }
    644   }
    645 }
    646 
    647 
    648 void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) {
    649   if (rt.is_reg()) {
    650     subu(rd, rs, rt.rm());
    651   } else {
    652     if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
    653       addiu(rd, rs, -rt.imm32_);  // No subiu instr, use addiu(x, y, -imm).
    654     } else {
    655       // li handles the relocation.
    656       ASSERT(!rs.is(at));
    657       li(at, rt);
    658       subu(rd, rs, at);
    659     }
    660   }
    661 }
    662 
    663 
    664 void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) {
    665   if (rt.is_reg()) {
    666     if (kArchVariant == kLoongson) {
    667       mult(rs, rt.rm());
    668       mflo(rd);
    669     } else {
    670       mul(rd, rs, rt.rm());
    671     }
    672   } else {
    673     // li handles the relocation.
    674     ASSERT(!rs.is(at));
    675     li(at, rt);
    676     if (kArchVariant == kLoongson) {
    677       mult(rs, at);
    678       mflo(rd);
    679     } else {
    680       mul(rd, rs, at);
    681     }
    682   }
    683 }
    684 
    685 
    686 void MacroAssembler::Mult(Register rs, const Operand& rt) {
    687   if (rt.is_reg()) {
    688     mult(rs, rt.rm());
    689   } else {
    690     // li handles the relocation.
    691     ASSERT(!rs.is(at));
    692     li(at, rt);
    693     mult(rs, at);
    694   }
    695 }
    696 
    697 
    698 void MacroAssembler::Multu(Register rs, const Operand& rt) {
    699   if (rt.is_reg()) {
    700     multu(rs, rt.rm());
    701   } else {
    702     // li handles the relocation.
    703     ASSERT(!rs.is(at));
    704     li(at, rt);
    705     multu(rs, at);
    706   }
    707 }
    708 
    709 
    710 void MacroAssembler::Div(Register rs, const Operand& rt) {
    711   if (rt.is_reg()) {
    712     div(rs, rt.rm());
    713   } else {
    714     // li handles the relocation.
    715     ASSERT(!rs.is(at));
    716     li(at, rt);
    717     div(rs, at);
    718   }
    719 }
    720 
    721 
    722 void MacroAssembler::Divu(Register rs, const Operand& rt) {
    723   if (rt.is_reg()) {
    724     divu(rs, rt.rm());
    725   } else {
    726     // li handles the relocation.
    727     ASSERT(!rs.is(at));
    728     li(at, rt);
    729     divu(rs, at);
    730   }
    731 }
    732 
    733 
    734 void MacroAssembler::And(Register rd, Register rs, const Operand& rt) {
    735   if (rt.is_reg()) {
    736     and_(rd, rs, rt.rm());
    737   } else {
    738     if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
    739       andi(rd, rs, rt.imm32_);
    740     } else {
    741       // li handles the relocation.
    742       ASSERT(!rs.is(at));
    743       li(at, rt);
    744       and_(rd, rs, at);
    745     }
    746   }
    747 }
    748 
    749 
    750 void MacroAssembler::Or(Register rd, Register rs, const Operand& rt) {
    751   if (rt.is_reg()) {
    752     or_(rd, rs, rt.rm());
    753   } else {
    754     if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
    755       ori(rd, rs, rt.imm32_);
    756     } else {
    757       // li handles the relocation.
    758       ASSERT(!rs.is(at));
    759       li(at, rt);
    760       or_(rd, rs, at);
    761     }
    762   }
    763 }
    764 
    765 
    766 void MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) {
    767   if (rt.is_reg()) {
    768     xor_(rd, rs, rt.rm());
    769   } else {
    770     if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
    771       xori(rd, rs, rt.imm32_);
    772     } else {
    773       // li handles the relocation.
    774       ASSERT(!rs.is(at));
    775       li(at, rt);
    776       xor_(rd, rs, at);
    777     }
    778   }
    779 }
    780 
    781 
    782 void MacroAssembler::Nor(Register rd, Register rs, const Operand& rt) {
    783   if (rt.is_reg()) {
    784     nor(rd, rs, rt.rm());
    785   } else {
    786     // li handles the relocation.
    787     ASSERT(!rs.is(at));
    788     li(at, rt);
    789     nor(rd, rs, at);
    790   }
    791 }
    792 
    793 
    794 void MacroAssembler::Neg(Register rs, const Operand& rt) {
    795   ASSERT(rt.is_reg());
    796   ASSERT(!at.is(rs));
    797   ASSERT(!at.is(rt.rm()));
    798   li(at, -1);
    799   xor_(rs, rt.rm(), at);
    800 }
    801 
    802 
    803 void MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) {
    804   if (rt.is_reg()) {
    805     slt(rd, rs, rt.rm());
    806   } else {
    807     if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
    808       slti(rd, rs, rt.imm32_);
    809     } else {
    810       // li handles the relocation.
    811       ASSERT(!rs.is(at));
    812       li(at, rt);
    813       slt(rd, rs, at);
    814     }
    815   }
    816 }
    817 
    818 
    819 void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) {
    820   if (rt.is_reg()) {
    821     sltu(rd, rs, rt.rm());
    822   } else {
    823     if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
    824       sltiu(rd, rs, rt.imm32_);
    825     } else {
    826       // li handles the relocation.
    827       ASSERT(!rs.is(at));
    828       li(at, rt);
    829       sltu(rd, rs, at);
    830     }
    831   }
    832 }
    833 
    834 
    835 void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) {
    836   if (kArchVariant == kMips32r2) {
    837     if (rt.is_reg()) {
    838       rotrv(rd, rs, rt.rm());
    839     } else {
    840       rotr(rd, rs, rt.imm32_);
    841     }
    842   } else {
    843     if (rt.is_reg()) {
    844       subu(at, zero_reg, rt.rm());
    845       sllv(at, rs, at);
    846       srlv(rd, rs, rt.rm());
    847       or_(rd, rd, at);
    848     } else {
    849       if (rt.imm32_ == 0) {
    850         srl(rd, rs, 0);
    851       } else {
    852         srl(at, rs, rt.imm32_);
    853         sll(rd, rs, (0x20 - rt.imm32_) & 0x1f);
    854         or_(rd, rd, at);
    855       }
    856     }
    857   }
    858 }
    859 
    860 
    861 void MacroAssembler::Pref(int32_t hint, const MemOperand& rs) {
    862   if (kArchVariant == kLoongson) {
    863     lw(zero_reg, rs);
    864   } else {
    865     pref(hint, rs);
    866   }
    867 }
    868 
    869 
    870 // ------------Pseudo-instructions-------------
    871 
    872 void MacroAssembler::Ulw(Register rd, const MemOperand& rs) {
    873   lwr(rd, rs);
    874   lwl(rd, MemOperand(rs.rm(), rs.offset() + 3));
    875 }
    876 
    877 
    878 void MacroAssembler::Usw(Register rd, const MemOperand& rs) {
    879   swr(rd, rs);
    880   swl(rd, MemOperand(rs.rm(), rs.offset() + 3));
    881 }
    882 
    883 
    884 void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) {
    885   AllowDeferredHandleDereference smi_check;
    886   if (value->IsSmi()) {
    887     li(dst, Operand(value), mode);
    888   } else {
    889     ASSERT(value->IsHeapObject());
    890     if (isolate()->heap()->InNewSpace(*value)) {
    891       Handle<Cell> cell = isolate()->factory()->NewCell(value);
    892       li(dst, Operand(cell));
    893       lw(dst, FieldMemOperand(dst, Cell::kValueOffset));
    894     } else {
    895       li(dst, Operand(value));
    896     }
    897   }
    898 }
    899 
    900 
    901 void MacroAssembler::li(Register rd, Operand j, LiFlags mode) {
    902   ASSERT(!j.is_reg());
    903   BlockTrampolinePoolScope block_trampoline_pool(this);
    904   if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) {
    905     // Normal load of an immediate value which does not need Relocation Info.
    906     if (is_int16(j.imm32_)) {
    907       addiu(rd, zero_reg, j.imm32_);
    908     } else if (!(j.imm32_ & kHiMask)) {
    909       ori(rd, zero_reg, j.imm32_);
    910     } else if (!(j.imm32_ & kImm16Mask)) {
    911       lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask);
    912     } else {
    913       lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask);
    914       ori(rd, rd, (j.imm32_ & kImm16Mask));
    915     }
    916   } else {
    917     if (MustUseReg(j.rmode_)) {
    918       RecordRelocInfo(j.rmode_, j.imm32_);
    919     }
    920     // We always need the same number of instructions as we may need to patch
    921     // this code to load another value which may need 2 instructions to load.
    922     lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask);
    923     ori(rd, rd, (j.imm32_ & kImm16Mask));
    924   }
    925 }
    926 
    927 
    928 void MacroAssembler::MultiPush(RegList regs) {
    929   int16_t num_to_push = NumberOfBitsSet(regs);
    930   int16_t stack_offset = num_to_push * kPointerSize;
    931 
    932   Subu(sp, sp, Operand(stack_offset));
    933   for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
    934     if ((regs & (1 << i)) != 0) {
    935       stack_offset -= kPointerSize;
    936       sw(ToRegister(i), MemOperand(sp, stack_offset));
    937     }
    938   }
    939 }
    940 
    941 
    942 void MacroAssembler::MultiPushReversed(RegList regs) {
    943   int16_t num_to_push = NumberOfBitsSet(regs);
    944   int16_t stack_offset = num_to_push * kPointerSize;
    945 
    946   Subu(sp, sp, Operand(stack_offset));
    947   for (int16_t i = 0; i < kNumRegisters; i++) {
    948     if ((regs & (1 << i)) != 0) {
    949       stack_offset -= kPointerSize;
    950       sw(ToRegister(i), MemOperand(sp, stack_offset));
    951     }
    952   }
    953 }
    954 
    955 
    956 void MacroAssembler::MultiPop(RegList regs) {
    957   int16_t stack_offset = 0;
    958 
    959   for (int16_t i = 0; i < kNumRegisters; i++) {
    960     if ((regs & (1 << i)) != 0) {
    961       lw(ToRegister(i), MemOperand(sp, stack_offset));
    962       stack_offset += kPointerSize;
    963     }
    964   }
    965   addiu(sp, sp, stack_offset);
    966 }
    967 
    968 
    969 void MacroAssembler::MultiPopReversed(RegList regs) {
    970   int16_t stack_offset = 0;
    971 
    972   for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
    973     if ((regs & (1 << i)) != 0) {
    974       lw(ToRegister(i), MemOperand(sp, stack_offset));
    975       stack_offset += kPointerSize;
    976     }
    977   }
    978   addiu(sp, sp, stack_offset);
    979 }
    980 
    981 
    982 void MacroAssembler::MultiPushFPU(RegList regs) {
    983   int16_t num_to_push = NumberOfBitsSet(regs);
    984   int16_t stack_offset = num_to_push * kDoubleSize;
    985 
    986   Subu(sp, sp, Operand(stack_offset));
    987   for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
    988     if ((regs & (1 << i)) != 0) {
    989       stack_offset -= kDoubleSize;
    990       sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
    991     }
    992   }
    993 }
    994 
    995 
    996 void MacroAssembler::MultiPushReversedFPU(RegList regs) {
    997   int16_t num_to_push = NumberOfBitsSet(regs);
    998   int16_t stack_offset = num_to_push * kDoubleSize;
    999 
   1000   Subu(sp, sp, Operand(stack_offset));
   1001   for (int16_t i = 0; i < kNumRegisters; i++) {
   1002     if ((regs & (1 << i)) != 0) {
   1003       stack_offset -= kDoubleSize;
   1004       sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
   1005     }
   1006   }
   1007 }
   1008 
   1009 
   1010 void MacroAssembler::MultiPopFPU(RegList regs) {
   1011   int16_t stack_offset = 0;
   1012 
   1013   for (int16_t i = 0; i < kNumRegisters; i++) {
   1014     if ((regs & (1 << i)) != 0) {
   1015       ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
   1016       stack_offset += kDoubleSize;
   1017     }
   1018   }
   1019   addiu(sp, sp, stack_offset);
   1020 }
   1021 
   1022 
   1023 void MacroAssembler::MultiPopReversedFPU(RegList regs) {
   1024   int16_t stack_offset = 0;
   1025 
   1026   for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
   1027     if ((regs & (1 << i)) != 0) {
   1028       ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
   1029       stack_offset += kDoubleSize;
   1030     }
   1031   }
   1032   addiu(sp, sp, stack_offset);
   1033 }
   1034 
   1035 
   1036 void MacroAssembler::FlushICache(Register address, unsigned instructions) {
   1037   RegList saved_regs = kJSCallerSaved | ra.bit();
   1038   MultiPush(saved_regs);
   1039   AllowExternalCallThatCantCauseGC scope(this);
   1040 
   1041   // Save to a0 in case address == t0.
   1042   Move(a0, address);
   1043   PrepareCallCFunction(2, t0);
   1044 
   1045   li(a1, instructions * kInstrSize);
   1046   CallCFunction(ExternalReference::flush_icache_function(isolate()), 2);
   1047   MultiPop(saved_regs);
   1048 }
   1049 
   1050 
   1051 void MacroAssembler::Ext(Register rt,
   1052                          Register rs,
   1053                          uint16_t pos,
   1054                          uint16_t size) {
   1055   ASSERT(pos < 32);
   1056   ASSERT(pos + size < 33);
   1057 
   1058   if (kArchVariant == kMips32r2) {
   1059     ext_(rt, rs, pos, size);
   1060   } else {
   1061     // Move rs to rt and shift it left then right to get the
   1062     // desired bitfield on the right side and zeroes on the left.
   1063     int shift_left = 32 - (pos + size);
   1064     sll(rt, rs, shift_left);  // Acts as a move if shift_left == 0.
   1065 
   1066     int shift_right = 32 - size;
   1067     if (shift_right > 0) {
   1068       srl(rt, rt, shift_right);
   1069     }
   1070   }
   1071 }
   1072 
   1073 
   1074 void MacroAssembler::Ins(Register rt,
   1075                          Register rs,
   1076                          uint16_t pos,
   1077                          uint16_t size) {
   1078   ASSERT(pos < 32);
   1079   ASSERT(pos + size <= 32);
   1080   ASSERT(size != 0);
   1081 
   1082   if (kArchVariant == kMips32r2) {
   1083     ins_(rt, rs, pos, size);
   1084   } else {
   1085     ASSERT(!rt.is(t8) && !rs.is(t8));
   1086     Subu(at, zero_reg, Operand(1));
   1087     srl(at, at, 32 - size);
   1088     and_(t8, rs, at);
   1089     sll(t8, t8, pos);
   1090     sll(at, at, pos);
   1091     nor(at, at, zero_reg);
   1092     and_(at, rt, at);
   1093     or_(rt, t8, at);
   1094   }
   1095 }
   1096 
   1097 
   1098 void MacroAssembler::Cvt_d_uw(FPURegister fd,
   1099                               FPURegister fs,
   1100                               FPURegister scratch) {
   1101   // Move the data from fs to t8.
   1102   mfc1(t8, fs);
   1103   Cvt_d_uw(fd, t8, scratch);
   1104 }
   1105 
   1106 
   1107 void MacroAssembler::Cvt_d_uw(FPURegister fd,
   1108                               Register rs,
   1109                               FPURegister scratch) {
   1110   // Convert rs to a FP value in fd (and fd + 1).
   1111   // We do this by converting rs minus the MSB to avoid sign conversion,
   1112   // then adding 2^31 to the result (if needed).
   1113 
   1114   ASSERT(!fd.is(scratch));
   1115   ASSERT(!rs.is(t9));
   1116   ASSERT(!rs.is(at));
   1117 
   1118   // Save rs's MSB to t9.
   1119   Ext(t9, rs, 31, 1);
   1120   // Remove rs's MSB.
   1121   Ext(at, rs, 0, 31);
   1122   // Move the result to fd.
   1123   mtc1(at, fd);
   1124 
   1125   // Convert fd to a real FP value.
   1126   cvt_d_w(fd, fd);
   1127 
   1128   Label conversion_done;
   1129 
   1130   // If rs's MSB was 0, it's done.
   1131   // Otherwise we need to add that to the FP register.
   1132   Branch(&conversion_done, eq, t9, Operand(zero_reg));
   1133 
   1134   // Load 2^31 into f20 as its float representation.
   1135   li(at, 0x41E00000);
   1136   mtc1(at, FPURegister::from_code(scratch.code() + 1));
   1137   mtc1(zero_reg, scratch);
   1138   // Add it to fd.
   1139   add_d(fd, fd, scratch);
   1140 
   1141   bind(&conversion_done);
   1142 }
   1143 
   1144 
   1145 void MacroAssembler::Trunc_uw_d(FPURegister fd,
   1146                                 FPURegister fs,
   1147                                 FPURegister scratch) {
   1148   Trunc_uw_d(fs, t8, scratch);
   1149   mtc1(t8, fd);
   1150 }
   1151 
   1152 
   1153 void MacroAssembler::Trunc_w_d(FPURegister fd, FPURegister fs) {
   1154   if (kArchVariant == kLoongson && fd.is(fs)) {
   1155     mfc1(t8, FPURegister::from_code(fs.code() + 1));
   1156     trunc_w_d(fd, fs);
   1157     mtc1(t8, FPURegister::from_code(fs.code() + 1));
   1158   } else {
   1159     trunc_w_d(fd, fs);
   1160   }
   1161 }
   1162 
   1163 
   1164 void MacroAssembler::Round_w_d(FPURegister fd, FPURegister fs) {
   1165   if (kArchVariant == kLoongson && fd.is(fs)) {
   1166     mfc1(t8, FPURegister::from_code(fs.code() + 1));
   1167     round_w_d(fd, fs);
   1168     mtc1(t8, FPURegister::from_code(fs.code() + 1));
   1169   } else {
   1170     round_w_d(fd, fs);
   1171   }
   1172 }
   1173 
   1174 
   1175 void MacroAssembler::Floor_w_d(FPURegister fd, FPURegister fs) {
   1176   if (kArchVariant == kLoongson && fd.is(fs)) {
   1177     mfc1(t8, FPURegister::from_code(fs.code() + 1));
   1178     floor_w_d(fd, fs);
   1179     mtc1(t8, FPURegister::from_code(fs.code() + 1));
   1180   } else {
   1181     floor_w_d(fd, fs);
   1182   }
   1183 }
   1184 
   1185 
   1186 void MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) {
   1187   if (kArchVariant == kLoongson && fd.is(fs)) {
   1188     mfc1(t8, FPURegister::from_code(fs.code() + 1));
   1189     ceil_w_d(fd, fs);
   1190     mtc1(t8, FPURegister::from_code(fs.code() + 1));
   1191   } else {
   1192     ceil_w_d(fd, fs);
   1193   }
   1194 }
   1195 
   1196 
   1197 void MacroAssembler::Trunc_uw_d(FPURegister fd,
   1198                                 Register rs,
   1199                                 FPURegister scratch) {
   1200   ASSERT(!fd.is(scratch));
   1201   ASSERT(!rs.is(at));
   1202 
   1203   // Load 2^31 into scratch as its float representation.
   1204   li(at, 0x41E00000);
   1205   mtc1(at, FPURegister::from_code(scratch.code() + 1));
   1206   mtc1(zero_reg, scratch);
   1207   // Test if scratch > fd.
   1208   // If fd < 2^31 we can convert it normally.
   1209   Label simple_convert;
   1210   BranchF(&simple_convert, NULL, lt, fd, scratch);
   1211 
   1212   // First we subtract 2^31 from fd, then trunc it to rs
   1213   // and add 2^31 to rs.
   1214   sub_d(scratch, fd, scratch);
   1215   trunc_w_d(scratch, scratch);
   1216   mfc1(rs, scratch);
   1217   Or(rs, rs, 1 << 31);
   1218 
   1219   Label done;
   1220   Branch(&done);
   1221   // Simple conversion.
   1222   bind(&simple_convert);
   1223   trunc_w_d(scratch, fd);
   1224   mfc1(rs, scratch);
   1225 
   1226   bind(&done);
   1227 }
   1228 
   1229 
   1230 void MacroAssembler::BranchF(Label* target,
   1231                              Label* nan,
   1232                              Condition cc,
   1233                              FPURegister cmp1,
   1234                              FPURegister cmp2,
   1235                              BranchDelaySlot bd) {
   1236   BlockTrampolinePoolScope block_trampoline_pool(this);
   1237   if (cc == al) {
   1238     Branch(bd, target);
   1239     return;
   1240   }
   1241 
   1242   ASSERT(nan || target);
   1243   // Check for unordered (NaN) cases.
   1244   if (nan) {
   1245     c(UN, D, cmp1, cmp2);
   1246     bc1t(nan);
   1247   }
   1248 
   1249   if (target) {
   1250     // Here NaN cases were either handled by this function or are assumed to
   1251     // have been handled by the caller.
   1252     // Unsigned conditions are treated as their signed counterpart.
   1253     switch (cc) {
   1254       case lt:
   1255         c(OLT, D, cmp1, cmp2);
   1256         bc1t(target);
   1257         break;
   1258       case gt:
   1259         c(ULE, D, cmp1, cmp2);
   1260         bc1f(target);
   1261         break;
   1262       case ge:
   1263         c(ULT, D, cmp1, cmp2);
   1264         bc1f(target);
   1265         break;
   1266       case le:
   1267         c(OLE, D, cmp1, cmp2);
   1268         bc1t(target);
   1269         break;
   1270       case eq:
   1271         c(EQ, D, cmp1, cmp2);
   1272         bc1t(target);
   1273         break;
   1274       case ueq:
   1275         c(UEQ, D, cmp1, cmp2);
   1276         bc1t(target);
   1277         break;
   1278       case ne:
   1279         c(EQ, D, cmp1, cmp2);
   1280         bc1f(target);
   1281         break;
   1282       case nue:
   1283         c(UEQ, D, cmp1, cmp2);
   1284         bc1f(target);
   1285         break;
   1286       default:
   1287         CHECK(0);
   1288     }
   1289   }
   1290 
   1291   if (bd == PROTECT) {
   1292     nop();
   1293   }
   1294 }
   1295 
   1296 
   1297 void MacroAssembler::Move(FPURegister dst, double imm) {
   1298   static const DoubleRepresentation minus_zero(-0.0);
   1299   static const DoubleRepresentation zero(0.0);
   1300   DoubleRepresentation value_rep(imm);
   1301   // Handle special values first.
   1302   bool force_load = dst.is(kDoubleRegZero);
   1303   if (value_rep == zero && !force_load) {
   1304     mov_d(dst, kDoubleRegZero);
   1305   } else if (value_rep == minus_zero && !force_load) {
   1306     neg_d(dst, kDoubleRegZero);
   1307   } else {
   1308     uint32_t lo, hi;
   1309     DoubleAsTwoUInt32(imm, &lo, &hi);
   1310     // Move the low part of the double into the lower of the corresponding FPU
   1311     // register of FPU register pair.
   1312     if (lo != 0) {
   1313       li(at, Operand(lo));
   1314       mtc1(at, dst);
   1315     } else {
   1316       mtc1(zero_reg, dst);
   1317     }
   1318     // Move the high part of the double into the higher of the corresponding FPU
   1319     // register of FPU register pair.
   1320     if (hi != 0) {
   1321       li(at, Operand(hi));
   1322       mtc1(at, dst.high());
   1323     } else {
   1324       mtc1(zero_reg, dst.high());
   1325     }
   1326   }
   1327 }
   1328 
   1329 
   1330 void MacroAssembler::Movz(Register rd, Register rs, Register rt) {
   1331   if (kArchVariant == kLoongson) {
   1332     Label done;
   1333     Branch(&done, ne, rt, Operand(zero_reg));
   1334     mov(rd, rs);
   1335     bind(&done);
   1336   } else {
   1337     movz(rd, rs, rt);
   1338   }
   1339 }
   1340 
   1341 
   1342 void MacroAssembler::Movn(Register rd, Register rs, Register rt) {
   1343   if (kArchVariant == kLoongson) {
   1344     Label done;
   1345     Branch(&done, eq, rt, Operand(zero_reg));
   1346     mov(rd, rs);
   1347     bind(&done);
   1348   } else {
   1349     movn(rd, rs, rt);
   1350   }
   1351 }
   1352 
   1353 
   1354 void MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) {
   1355   if (kArchVariant == kLoongson) {
   1356     // Tests an FP condition code and then conditionally move rs to rd.
   1357     // We do not currently use any FPU cc bit other than bit 0.
   1358     ASSERT(cc == 0);
   1359     ASSERT(!(rs.is(t8) || rd.is(t8)));
   1360     Label done;
   1361     Register scratch = t8;
   1362     // For testing purposes we need to fetch content of the FCSR register and
   1363     // than test its cc (floating point condition code) bit (for cc = 0, it is
   1364     // 24. bit of the FCSR).
   1365     cfc1(scratch, FCSR);
   1366     // For the MIPS I, II and III architectures, the contents of scratch is
   1367     // UNPREDICTABLE for the instruction immediately following CFC1.
   1368     nop();
   1369     srl(scratch, scratch, 16);
   1370     andi(scratch, scratch, 0x0080);
   1371     Branch(&done, eq, scratch, Operand(zero_reg));
   1372     mov(rd, rs);
   1373     bind(&done);
   1374   } else {
   1375     movt(rd, rs, cc);
   1376   }
   1377 }
   1378 
   1379 
   1380 void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) {
   1381   if (kArchVariant == kLoongson) {
   1382     // Tests an FP condition code and then conditionally move rs to rd.
   1383     // We do not currently use any FPU cc bit other than bit 0.
   1384     ASSERT(cc == 0);
   1385     ASSERT(!(rs.is(t8) || rd.is(t8)));
   1386     Label done;
   1387     Register scratch = t8;
   1388     // For testing purposes we need to fetch content of the FCSR register and
   1389     // than test its cc (floating point condition code) bit (for cc = 0, it is
   1390     // 24. bit of the FCSR).
   1391     cfc1(scratch, FCSR);
   1392     // For the MIPS I, II and III architectures, the contents of scratch is
   1393     // UNPREDICTABLE for the instruction immediately following CFC1.
   1394     nop();
   1395     srl(scratch, scratch, 16);
   1396     andi(scratch, scratch, 0x0080);
   1397     Branch(&done, ne, scratch, Operand(zero_reg));
   1398     mov(rd, rs);
   1399     bind(&done);
   1400   } else {
   1401     movf(rd, rs, cc);
   1402   }
   1403 }
   1404 
   1405 
   1406 void MacroAssembler::Clz(Register rd, Register rs) {
   1407   if (kArchVariant == kLoongson) {
   1408     ASSERT(!(rd.is(t8) || rd.is(t9)) && !(rs.is(t8) || rs.is(t9)));
   1409     Register mask = t8;
   1410     Register scratch = t9;
   1411     Label loop, end;
   1412     mov(at, rs);
   1413     mov(rd, zero_reg);
   1414     lui(mask, 0x8000);
   1415     bind(&loop);
   1416     and_(scratch, at, mask);
   1417     Branch(&end, ne, scratch, Operand(zero_reg));
   1418     addiu(rd, rd, 1);
   1419     Branch(&loop, ne, mask, Operand(zero_reg), USE_DELAY_SLOT);
   1420     srl(mask, mask, 1);
   1421     bind(&end);
   1422   } else {
   1423     clz(rd, rs);
   1424   }
   1425 }
   1426 
   1427 
   1428 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
   1429                                      Register result,
   1430                                      DoubleRegister double_input,
   1431                                      Register scratch,
   1432                                      DoubleRegister double_scratch,
   1433                                      Register except_flag,
   1434                                      CheckForInexactConversion check_inexact) {
   1435   ASSERT(!result.is(scratch));
   1436   ASSERT(!double_input.is(double_scratch));
   1437   ASSERT(!except_flag.is(scratch));
   1438 
   1439   Label done;
   1440 
   1441   // Clear the except flag (0 = no exception)
   1442   mov(except_flag, zero_reg);
   1443 
   1444   // Test for values that can be exactly represented as a signed 32-bit integer.
   1445   cvt_w_d(double_scratch, double_input);
   1446   mfc1(result, double_scratch);
   1447   cvt_d_w(double_scratch, double_scratch);
   1448   BranchF(&done, NULL, eq, double_input, double_scratch);
   1449 
   1450   int32_t except_mask = kFCSRFlagMask;  // Assume interested in all exceptions.
   1451 
   1452   if (check_inexact == kDontCheckForInexactConversion) {
   1453     // Ignore inexact exceptions.
   1454     except_mask &= ~kFCSRInexactFlagMask;
   1455   }
   1456 
   1457   // Save FCSR.
   1458   cfc1(scratch, FCSR);
   1459   // Disable FPU exceptions.
   1460   ctc1(zero_reg, FCSR);
   1461 
   1462   // Do operation based on rounding mode.
   1463   switch (rounding_mode) {
   1464     case kRoundToNearest:
   1465       Round_w_d(double_scratch, double_input);
   1466       break;
   1467     case kRoundToZero:
   1468       Trunc_w_d(double_scratch, double_input);
   1469       break;
   1470     case kRoundToPlusInf:
   1471       Ceil_w_d(double_scratch, double_input);
   1472       break;
   1473     case kRoundToMinusInf:
   1474       Floor_w_d(double_scratch, double_input);
   1475       break;
   1476   }  // End of switch-statement.
   1477 
   1478   // Retrieve FCSR.
   1479   cfc1(except_flag, FCSR);
   1480   // Restore FCSR.
   1481   ctc1(scratch, FCSR);
   1482   // Move the converted value into the result register.
   1483   mfc1(result, double_scratch);
   1484 
   1485   // Check for fpu exceptions.
   1486   And(except_flag, except_flag, Operand(except_mask));
   1487 
   1488   bind(&done);
   1489 }
   1490 
   1491 
   1492 void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
   1493                                                 DoubleRegister double_input,
   1494                                                 Label* done) {
   1495   DoubleRegister single_scratch = kLithiumScratchDouble.low();
   1496   Register scratch = at;
   1497   Register scratch2 = t9;
   1498 
   1499   // Clear cumulative exception flags and save the FCSR.
   1500   cfc1(scratch2, FCSR);
   1501   ctc1(zero_reg, FCSR);
   1502   // Try a conversion to a signed integer.
   1503   trunc_w_d(single_scratch, double_input);
   1504   mfc1(result, single_scratch);
   1505   // Retrieve and restore the FCSR.
   1506   cfc1(scratch, FCSR);
   1507   ctc1(scratch2, FCSR);
   1508   // Check for overflow and NaNs.
   1509   And(scratch,
   1510       scratch,
   1511       kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask);
   1512   // If we had no exceptions we are done.
   1513   Branch(done, eq, scratch, Operand(zero_reg));
   1514 }
   1515 
   1516 
   1517 void MacroAssembler::TruncateDoubleToI(Register result,
   1518                                        DoubleRegister double_input) {
   1519   Label done;
   1520 
   1521   TryInlineTruncateDoubleToI(result, double_input, &done);
   1522 
   1523   // If we fell through then inline version didn't succeed - call stub instead.
   1524   push(ra);
   1525   Subu(sp, sp, Operand(kDoubleSize));  // Put input on stack.
   1526   sdc1(double_input, MemOperand(sp, 0));
   1527 
   1528   DoubleToIStub stub(isolate(), sp, result, 0, true, true);
   1529   CallStub(&stub);
   1530 
   1531   Addu(sp, sp, Operand(kDoubleSize));
   1532   pop(ra);
   1533 
   1534   bind(&done);
   1535 }
   1536 
   1537 
   1538 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
   1539   Label done;
   1540   DoubleRegister double_scratch = f12;
   1541   ASSERT(!result.is(object));
   1542 
   1543   ldc1(double_scratch,
   1544        MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
   1545   TryInlineTruncateDoubleToI(result, double_scratch, &done);
   1546 
   1547   // If we fell through then inline version didn't succeed - call stub instead.
   1548   push(ra);
   1549   DoubleToIStub stub(isolate(),
   1550                      object,
   1551                      result,
   1552                      HeapNumber::kValueOffset - kHeapObjectTag,
   1553                      true,
   1554                      true);
   1555   CallStub(&stub);
   1556   pop(ra);
   1557 
   1558   bind(&done);
   1559 }
   1560 
   1561 
   1562 void MacroAssembler::TruncateNumberToI(Register object,
   1563                                        Register result,
   1564                                        Register heap_number_map,
   1565                                        Register scratch,
   1566                                        Label* not_number) {
   1567   Label done;
   1568   ASSERT(!result.is(object));
   1569 
   1570   UntagAndJumpIfSmi(result, object, &done);
   1571   JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number);
   1572   TruncateHeapNumberToI(result, object);
   1573 
   1574   bind(&done);
   1575 }
   1576 
   1577 
   1578 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
   1579                                          Register src,
   1580                                          int num_least_bits) {
   1581   Ext(dst, src, kSmiTagSize, num_least_bits);
   1582 }
   1583 
   1584 
   1585 void MacroAssembler::GetLeastBitsFromInt32(Register dst,
   1586                                            Register src,
   1587                                            int num_least_bits) {
   1588   And(dst, src, Operand((1 << num_least_bits) - 1));
   1589 }
   1590 
   1591 
   1592 // Emulated condtional branches do not emit a nop in the branch delay slot.
   1593 //
   1594 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct.
   1595 #define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT(                                \
   1596     (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) ||          \
   1597     (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg))))
   1598 
   1599 
   1600 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) {
   1601   BranchShort(offset, bdslot);
   1602 }
   1603 
   1604 
   1605 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs,
   1606                             const Operand& rt,
   1607                             BranchDelaySlot bdslot) {
   1608   BranchShort(offset, cond, rs, rt, bdslot);
   1609 }
   1610 
   1611 
   1612 void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) {
   1613   if (L->is_bound()) {
   1614     if (is_near(L)) {
   1615       BranchShort(L, bdslot);
   1616     } else {
   1617       Jr(L, bdslot);
   1618     }
   1619   } else {
   1620     if (is_trampoline_emitted()) {
   1621       Jr(L, bdslot);
   1622     } else {
   1623       BranchShort(L, bdslot);
   1624     }
   1625   }
   1626 }
   1627 
   1628 
   1629 void MacroAssembler::Branch(Label* L, Condition cond, Register rs,
   1630                             const Operand& rt,
   1631                             BranchDelaySlot bdslot) {
   1632   if (L->is_bound()) {
   1633     if (is_near(L)) {
   1634       BranchShort(L, cond, rs, rt, bdslot);
   1635     } else {
   1636       if (cond != cc_always) {
   1637         Label skip;
   1638         Condition neg_cond = NegateCondition(cond);
   1639         BranchShort(&skip, neg_cond, rs, rt);
   1640         Jr(L, bdslot);
   1641         bind(&skip);
   1642       } else {
   1643         Jr(L, bdslot);
   1644       }
   1645     }
   1646   } else {
   1647     if (is_trampoline_emitted()) {
   1648       if (cond != cc_always) {
   1649         Label skip;
   1650         Condition neg_cond = NegateCondition(cond);
   1651         BranchShort(&skip, neg_cond, rs, rt);
   1652         Jr(L, bdslot);
   1653         bind(&skip);
   1654       } else {
   1655         Jr(L, bdslot);
   1656       }
   1657     } else {
   1658       BranchShort(L, cond, rs, rt, bdslot);
   1659     }
   1660   }
   1661 }
   1662 
   1663 
   1664 void MacroAssembler::Branch(Label* L,
   1665                             Condition cond,
   1666                             Register rs,
   1667                             Heap::RootListIndex index,
   1668                             BranchDelaySlot bdslot) {
   1669   LoadRoot(at, index);
   1670   Branch(L, cond, rs, Operand(at), bdslot);
   1671 }
   1672 
   1673 
   1674 void MacroAssembler::BranchShort(int16_t offset, BranchDelaySlot bdslot) {
   1675   b(offset);
   1676 
   1677   // Emit a nop in the branch delay slot if required.
   1678   if (bdslot == PROTECT)
   1679     nop();
   1680 }
   1681 
   1682 
   1683 void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs,
   1684                                  const Operand& rt,
   1685                                  BranchDelaySlot bdslot) {
   1686   BRANCH_ARGS_CHECK(cond, rs, rt);
   1687   ASSERT(!rs.is(zero_reg));
   1688   Register r2 = no_reg;
   1689   Register scratch = at;
   1690 
   1691   if (rt.is_reg()) {
   1692     // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or
   1693     // rt.
   1694     BlockTrampolinePoolScope block_trampoline_pool(this);
   1695     r2 = rt.rm_;
   1696     switch (cond) {
   1697       case cc_always:
   1698         b(offset);
   1699         break;
   1700       case eq:
   1701         beq(rs, r2, offset);
   1702         break;
   1703       case ne:
   1704         bne(rs, r2, offset);
   1705         break;
   1706       // Signed comparison.
   1707       case greater:
   1708         if (r2.is(zero_reg)) {
   1709           bgtz(rs, offset);
   1710         } else {
   1711           slt(scratch, r2, rs);
   1712           bne(scratch, zero_reg, offset);
   1713         }
   1714         break;
   1715       case greater_equal:
   1716         if (r2.is(zero_reg)) {
   1717           bgez(rs, offset);
   1718         } else {
   1719           slt(scratch, rs, r2);
   1720           beq(scratch, zero_reg, offset);
   1721         }
   1722         break;
   1723       case less:
   1724         if (r2.is(zero_reg)) {
   1725           bltz(rs, offset);
   1726         } else {
   1727           slt(scratch, rs, r2);
   1728           bne(scratch, zero_reg, offset);
   1729         }
   1730         break;
   1731       case less_equal:
   1732         if (r2.is(zero_reg)) {
   1733           blez(rs, offset);
   1734         } else {
   1735           slt(scratch, r2, rs);
   1736           beq(scratch, zero_reg, offset);
   1737         }
   1738         break;
   1739       // Unsigned comparison.
   1740       case Ugreater:
   1741         if (r2.is(zero_reg)) {
   1742           bgtz(rs, offset);
   1743         } else {
   1744           sltu(scratch, r2, rs);
   1745           bne(scratch, zero_reg, offset);
   1746         }
   1747         break;
   1748       case Ugreater_equal:
   1749         if (r2.is(zero_reg)) {
   1750           bgez(rs, offset);
   1751         } else {
   1752           sltu(scratch, rs, r2);
   1753           beq(scratch, zero_reg, offset);
   1754         }
   1755         break;
   1756       case Uless:
   1757         if (r2.is(zero_reg)) {
   1758           // No code needs to be emitted.
   1759           return;
   1760         } else {
   1761           sltu(scratch, rs, r2);
   1762           bne(scratch, zero_reg, offset);
   1763         }
   1764         break;
   1765       case Uless_equal:
   1766         if (r2.is(zero_reg)) {
   1767           b(offset);
   1768         } else {
   1769           sltu(scratch, r2, rs);
   1770           beq(scratch, zero_reg, offset);
   1771         }
   1772         break;
   1773       default:
   1774         UNREACHABLE();
   1775     }
   1776   } else {
   1777     // Be careful to always use shifted_branch_offset only just before the
   1778     // branch instruction, as the location will be remember for patching the
   1779     // target.
   1780     BlockTrampolinePoolScope block_trampoline_pool(this);
   1781     switch (cond) {
   1782       case cc_always:
   1783         b(offset);
   1784         break;
   1785       case eq:
   1786         // We don't want any other register but scratch clobbered.
   1787         ASSERT(!scratch.is(rs));
   1788         r2 = scratch;
   1789         li(r2, rt);
   1790         beq(rs, r2, offset);
   1791         break;
   1792       case ne:
   1793         // We don't want any other register but scratch clobbered.
   1794         ASSERT(!scratch.is(rs));
   1795         r2 = scratch;
   1796         li(r2, rt);
   1797         bne(rs, r2, offset);
   1798         break;
   1799       // Signed comparison.
   1800       case greater:
   1801         if (rt.imm32_ == 0) {
   1802           bgtz(rs, offset);
   1803         } else {
   1804           r2 = scratch;
   1805           li(r2, rt);
   1806           slt(scratch, r2, rs);
   1807           bne(scratch, zero_reg, offset);
   1808         }
   1809         break;
   1810       case greater_equal:
   1811         if (rt.imm32_ == 0) {
   1812           bgez(rs, offset);
   1813         } else if (is_int16(rt.imm32_)) {
   1814           slti(scratch, rs, rt.imm32_);
   1815           beq(scratch, zero_reg, offset);
   1816         } else {
   1817           r2 = scratch;
   1818           li(r2, rt);
   1819           slt(scratch, rs, r2);
   1820           beq(scratch, zero_reg, offset);
   1821         }
   1822         break;
   1823       case less:
   1824         if (rt.imm32_ == 0) {
   1825           bltz(rs, offset);
   1826         } else if (is_int16(rt.imm32_)) {
   1827           slti(scratch, rs, rt.imm32_);
   1828           bne(scratch, zero_reg, offset);
   1829         } else {
   1830           r2 = scratch;
   1831           li(r2, rt);
   1832           slt(scratch, rs, r2);
   1833           bne(scratch, zero_reg, offset);
   1834         }
   1835         break;
   1836       case less_equal:
   1837         if (rt.imm32_ == 0) {
   1838           blez(rs, offset);
   1839         } else {
   1840           r2 = scratch;
   1841           li(r2, rt);
   1842           slt(scratch, r2, rs);
   1843           beq(scratch, zero_reg, offset);
   1844        }
   1845        break;
   1846       // Unsigned comparison.
   1847       case Ugreater:
   1848         if (rt.imm32_ == 0) {
   1849           bgtz(rs, offset);
   1850         } else {
   1851           r2 = scratch;
   1852           li(r2, rt);
   1853           sltu(scratch, r2, rs);
   1854           bne(scratch, zero_reg, offset);
   1855         }
   1856         break;
   1857       case Ugreater_equal:
   1858         if (rt.imm32_ == 0) {
   1859           bgez(rs, offset);
   1860         } else if (is_int16(rt.imm32_)) {
   1861           sltiu(scratch, rs, rt.imm32_);
   1862           beq(scratch, zero_reg, offset);
   1863         } else {
   1864           r2 = scratch;
   1865           li(r2, rt);
   1866           sltu(scratch, rs, r2);
   1867           beq(scratch, zero_reg, offset);
   1868         }
   1869         break;
   1870       case Uless:
   1871         if (rt.imm32_ == 0) {
   1872           // No code needs to be emitted.
   1873           return;
   1874         } else if (is_int16(rt.imm32_)) {
   1875           sltiu(scratch, rs, rt.imm32_);
   1876           bne(scratch, zero_reg, offset);
   1877         } else {
   1878           r2 = scratch;
   1879           li(r2, rt);
   1880           sltu(scratch, rs, r2);
   1881           bne(scratch, zero_reg, offset);
   1882         }
   1883         break;
   1884       case Uless_equal:
   1885         if (rt.imm32_ == 0) {
   1886           b(offset);
   1887         } else {
   1888           r2 = scratch;
   1889           li(r2, rt);
   1890           sltu(scratch, r2, rs);
   1891           beq(scratch, zero_reg, offset);
   1892         }
   1893         break;
   1894       default:
   1895         UNREACHABLE();
   1896     }
   1897   }
   1898   // Emit a nop in the branch delay slot if required.
   1899   if (bdslot == PROTECT)
   1900     nop();
   1901 }
   1902 
   1903 
   1904 void MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) {
   1905   // We use branch_offset as an argument for the branch instructions to be sure
   1906   // it is called just before generating the branch instruction, as needed.
   1907 
   1908   b(shifted_branch_offset(L, false));
   1909 
   1910   // Emit a nop in the branch delay slot if required.
   1911   if (bdslot == PROTECT)
   1912     nop();
   1913 }
   1914 
   1915 
   1916 void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
   1917                                  const Operand& rt,
   1918                                  BranchDelaySlot bdslot) {
   1919   BRANCH_ARGS_CHECK(cond, rs, rt);
   1920 
   1921   int32_t offset = 0;
   1922   Register r2 = no_reg;
   1923   Register scratch = at;
   1924   if (rt.is_reg()) {
   1925     BlockTrampolinePoolScope block_trampoline_pool(this);
   1926     r2 = rt.rm_;
   1927     // Be careful to always use shifted_branch_offset only just before the
   1928     // branch instruction, as the location will be remember for patching the
   1929     // target.
   1930     switch (cond) {
   1931       case cc_always:
   1932         offset = shifted_branch_offset(L, false);
   1933         b(offset);
   1934         break;
   1935       case eq:
   1936         offset = shifted_branch_offset(L, false);
   1937         beq(rs, r2, offset);
   1938         break;
   1939       case ne:
   1940         offset = shifted_branch_offset(L, false);
   1941         bne(rs, r2, offset);
   1942         break;
   1943       // Signed comparison.
   1944       case greater:
   1945         if (r2.is(zero_reg)) {
   1946           offset = shifted_branch_offset(L, false);
   1947           bgtz(rs, offset);
   1948         } else {
   1949           slt(scratch, r2, rs);
   1950           offset = shifted_branch_offset(L, false);
   1951           bne(scratch, zero_reg, offset);
   1952         }
   1953         break;
   1954       case greater_equal:
   1955         if (r2.is(zero_reg)) {
   1956           offset = shifted_branch_offset(L, false);
   1957           bgez(rs, offset);
   1958         } else {
   1959           slt(scratch, rs, r2);
   1960           offset = shifted_branch_offset(L, false);
   1961           beq(scratch, zero_reg, offset);
   1962         }
   1963         break;
   1964       case less:
   1965         if (r2.is(zero_reg)) {
   1966           offset = shifted_branch_offset(L, false);
   1967           bltz(rs, offset);
   1968         } else {
   1969           slt(scratch, rs, r2);
   1970           offset = shifted_branch_offset(L, false);
   1971           bne(scratch, zero_reg, offset);
   1972         }
   1973         break;
   1974       case less_equal:
   1975         if (r2.is(zero_reg)) {
   1976           offset = shifted_branch_offset(L, false);
   1977           blez(rs, offset);
   1978         } else {
   1979           slt(scratch, r2, rs);
   1980           offset = shifted_branch_offset(L, false);
   1981           beq(scratch, zero_reg, offset);
   1982         }
   1983         break;
   1984       // Unsigned comparison.
   1985       case Ugreater:
   1986         if (r2.is(zero_reg)) {
   1987           offset = shifted_branch_offset(L, false);
   1988            bgtz(rs, offset);
   1989         } else {
   1990           sltu(scratch, r2, rs);
   1991           offset = shifted_branch_offset(L, false);
   1992           bne(scratch, zero_reg, offset);
   1993         }
   1994         break;
   1995       case Ugreater_equal:
   1996         if (r2.is(zero_reg)) {
   1997           offset = shifted_branch_offset(L, false);
   1998           bgez(rs, offset);
   1999         } else {
   2000           sltu(scratch, rs, r2);
   2001           offset = shifted_branch_offset(L, false);
   2002           beq(scratch, zero_reg, offset);
   2003         }
   2004         break;
   2005       case Uless:
   2006         if (r2.is(zero_reg)) {
   2007           // No code needs to be emitted.
   2008           return;
   2009         } else {
   2010           sltu(scratch, rs, r2);
   2011           offset = shifted_branch_offset(L, false);
   2012           bne(scratch, zero_reg, offset);
   2013         }
   2014         break;
   2015       case Uless_equal:
   2016         if (r2.is(zero_reg)) {
   2017           offset = shifted_branch_offset(L, false);
   2018           b(offset);
   2019         } else {
   2020           sltu(scratch, r2, rs);
   2021           offset = shifted_branch_offset(L, false);
   2022           beq(scratch, zero_reg, offset);
   2023         }
   2024         break;
   2025       default:
   2026         UNREACHABLE();
   2027     }
   2028   } else {
   2029     // Be careful to always use shifted_branch_offset only just before the
   2030     // branch instruction, as the location will be remember for patching the
   2031     // target.
   2032     BlockTrampolinePoolScope block_trampoline_pool(this);
   2033     switch (cond) {
   2034       case cc_always:
   2035         offset = shifted_branch_offset(L, false);
   2036         b(offset);
   2037         break;
   2038       case eq:
   2039         ASSERT(!scratch.is(rs));
   2040         r2 = scratch;
   2041         li(r2, rt);
   2042         offset = shifted_branch_offset(L, false);
   2043         beq(rs, r2, offset);
   2044         break;
   2045       case ne:
   2046         ASSERT(!scratch.is(rs));
   2047         r2 = scratch;
   2048         li(r2, rt);
   2049         offset = shifted_branch_offset(L, false);
   2050         bne(rs, r2, offset);
   2051         break;
   2052       // Signed comparison.
   2053       case greater:
   2054         if (rt.imm32_ == 0) {
   2055           offset = shifted_branch_offset(L, false);
   2056           bgtz(rs, offset);
   2057         } else {
   2058           ASSERT(!scratch.is(rs));
   2059           r2 = scratch;
   2060           li(r2, rt);
   2061           slt(scratch, r2, rs);
   2062           offset = shifted_branch_offset(L, false);
   2063           bne(scratch, zero_reg, offset);
   2064         }
   2065         break;
   2066       case greater_equal:
   2067         if (rt.imm32_ == 0) {
   2068           offset = shifted_branch_offset(L, false);
   2069           bgez(rs, offset);
   2070         } else if (is_int16(rt.imm32_)) {
   2071           slti(scratch, rs, rt.imm32_);
   2072           offset = shifted_branch_offset(L, false);
   2073           beq(scratch, zero_reg, offset);
   2074         } else {
   2075           ASSERT(!scratch.is(rs));
   2076           r2 = scratch;
   2077           li(r2, rt);
   2078           slt(scratch, rs, r2);
   2079           offset = shifted_branch_offset(L, false);
   2080           beq(scratch, zero_reg, offset);
   2081         }
   2082         break;
   2083       case less:
   2084         if (rt.imm32_ == 0) {
   2085           offset = shifted_branch_offset(L, false);
   2086           bltz(rs, offset);
   2087         } else if (is_int16(rt.imm32_)) {
   2088           slti(scratch, rs, rt.imm32_);
   2089           offset = shifted_branch_offset(L, false);
   2090           bne(scratch, zero_reg, offset);
   2091         } else {
   2092           ASSERT(!scratch.is(rs));
   2093           r2 = scratch;
   2094           li(r2, rt);
   2095           slt(scratch, rs, r2);
   2096           offset = shifted_branch_offset(L, false);
   2097           bne(scratch, zero_reg, offset);
   2098         }
   2099         break;
   2100       case less_equal:
   2101         if (rt.imm32_ == 0) {
   2102           offset = shifted_branch_offset(L, false);
   2103           blez(rs, offset);
   2104         } else {
   2105           ASSERT(!scratch.is(rs));
   2106           r2 = scratch;
   2107           li(r2, rt);
   2108           slt(scratch, r2, rs);
   2109           offset = shifted_branch_offset(L, false);
   2110           beq(scratch, zero_reg, offset);
   2111         }
   2112         break;
   2113       // Unsigned comparison.
   2114       case Ugreater:
   2115         if (rt.imm32_ == 0) {
   2116           offset = shifted_branch_offset(L, false);
   2117           bne(rs, zero_reg, offset);
   2118         } else {
   2119           ASSERT(!scratch.is(rs));
   2120           r2 = scratch;
   2121           li(r2, rt);
   2122           sltu(scratch, r2, rs);
   2123           offset = shifted_branch_offset(L, false);
   2124           bne(scratch, zero_reg, offset);
   2125         }
   2126         break;
   2127       case Ugreater_equal:
   2128         if (rt.imm32_ == 0) {
   2129           offset = shifted_branch_offset(L, false);
   2130           bgez(rs, offset);
   2131         } else if (is_int16(rt.imm32_)) {
   2132           sltiu(scratch, rs, rt.imm32_);
   2133           offset = shifted_branch_offset(L, false);
   2134           beq(scratch, zero_reg, offset);
   2135         } else {
   2136           ASSERT(!scratch.is(rs));
   2137           r2 = scratch;
   2138           li(r2, rt);
   2139           sltu(scratch, rs, r2);
   2140           offset = shifted_branch_offset(L, false);
   2141           beq(scratch, zero_reg, offset);
   2142         }
   2143         break;
   2144      case Uless:
   2145         if (rt.imm32_ == 0) {
   2146           // No code needs to be emitted.
   2147           return;
   2148         } else if (is_int16(rt.imm32_)) {
   2149           sltiu(scratch, rs, rt.imm32_);
   2150           offset = shifted_branch_offset(L, false);
   2151           bne(scratch, zero_reg, offset);
   2152         } else {
   2153           ASSERT(!scratch.is(rs));
   2154           r2 = scratch;
   2155           li(r2, rt);
   2156           sltu(scratch, rs, r2);
   2157           offset = shifted_branch_offset(L, false);
   2158           bne(scratch, zero_reg, offset);
   2159         }
   2160         break;
   2161       case Uless_equal:
   2162         if (rt.imm32_ == 0) {
   2163           offset = shifted_branch_offset(L, false);
   2164           beq(rs, zero_reg, offset);
   2165         } else {
   2166           ASSERT(!scratch.is(rs));
   2167           r2 = scratch;
   2168           li(r2, rt);
   2169           sltu(scratch, r2, rs);
   2170           offset = shifted_branch_offset(L, false);
   2171           beq(scratch, zero_reg, offset);
   2172         }
   2173         break;
   2174       default:
   2175         UNREACHABLE();
   2176     }
   2177   }
   2178   // Check that offset could actually hold on an int16_t.
   2179   ASSERT(is_int16(offset));
   2180   // Emit a nop in the branch delay slot if required.
   2181   if (bdslot == PROTECT)
   2182     nop();
   2183 }
   2184 
   2185 
   2186 void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) {
   2187   BranchAndLinkShort(offset, bdslot);
   2188 }
   2189 
   2190 
   2191 void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs,
   2192                                    const Operand& rt,
   2193                                    BranchDelaySlot bdslot) {
   2194   BranchAndLinkShort(offset, cond, rs, rt, bdslot);
   2195 }
   2196 
   2197 
   2198 void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) {
   2199   if (L->is_bound()) {
   2200     if (is_near(L)) {
   2201       BranchAndLinkShort(L, bdslot);
   2202     } else {
   2203       Jalr(L, bdslot);
   2204     }
   2205   } else {
   2206     if (is_trampoline_emitted()) {
   2207       Jalr(L, bdslot);
   2208     } else {
   2209       BranchAndLinkShort(L, bdslot);
   2210     }
   2211   }
   2212 }
   2213 
   2214 
   2215 void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs,
   2216                                    const Operand& rt,
   2217                                    BranchDelaySlot bdslot) {
   2218   if (L->is_bound()) {
   2219     if (is_near(L)) {
   2220       BranchAndLinkShort(L, cond, rs, rt, bdslot);
   2221     } else {
   2222       Label skip;
   2223       Condition neg_cond = NegateCondition(cond);
   2224       BranchShort(&skip, neg_cond, rs, rt);
   2225       Jalr(L, bdslot);
   2226       bind(&skip);
   2227     }
   2228   } else {
   2229     if (is_trampoline_emitted()) {
   2230       Label skip;
   2231       Condition neg_cond = NegateCondition(cond);
   2232       BranchShort(&skip, neg_cond, rs, rt);
   2233       Jalr(L, bdslot);
   2234       bind(&skip);
   2235     } else {
   2236       BranchAndLinkShort(L, cond, rs, rt, bdslot);
   2237     }
   2238   }
   2239 }
   2240 
   2241 
   2242 // We need to use a bgezal or bltzal, but they can't be used directly with the
   2243 // slt instructions. We could use sub or add instead but we would miss overflow
   2244 // cases, so we keep slt and add an intermediate third instruction.
   2245 void MacroAssembler::BranchAndLinkShort(int16_t offset,
   2246                                         BranchDelaySlot bdslot) {
   2247   bal(offset);
   2248 
   2249   // Emit a nop in the branch delay slot if required.
   2250   if (bdslot == PROTECT)
   2251     nop();
   2252 }
   2253 
   2254 
   2255 void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond,
   2256                                         Register rs, const Operand& rt,
   2257                                         BranchDelaySlot bdslot) {
   2258   BRANCH_ARGS_CHECK(cond, rs, rt);
   2259   Register r2 = no_reg;
   2260   Register scratch = at;
   2261 
   2262   if (rt.is_reg()) {
   2263     r2 = rt.rm_;
   2264   } else if (cond != cc_always) {
   2265     r2 = scratch;
   2266     li(r2, rt);
   2267   }
   2268 
   2269   {
   2270     BlockTrampolinePoolScope block_trampoline_pool(this);
   2271     switch (cond) {
   2272       case cc_always:
   2273         bal(offset);
   2274         break;
   2275       case eq:
   2276         bne(rs, r2, 2);
   2277         nop();
   2278         bal(offset);
   2279         break;
   2280       case ne:
   2281         beq(rs, r2, 2);
   2282         nop();
   2283         bal(offset);
   2284         break;
   2285 
   2286       // Signed comparison.
   2287       case greater:
   2288         slt(scratch, r2, rs);
   2289         addiu(scratch, scratch, -1);
   2290         bgezal(scratch, offset);
   2291         break;
   2292       case greater_equal:
   2293         slt(scratch, rs, r2);
   2294         addiu(scratch, scratch, -1);
   2295         bltzal(scratch, offset);
   2296         break;
   2297       case less:
   2298         slt(scratch, rs, r2);
   2299         addiu(scratch, scratch, -1);
   2300         bgezal(scratch, offset);
   2301         break;
   2302       case less_equal:
   2303         slt(scratch, r2, rs);
   2304         addiu(scratch, scratch, -1);
   2305         bltzal(scratch, offset);
   2306         break;
   2307 
   2308       // Unsigned comparison.
   2309       case Ugreater:
   2310         sltu(scratch, r2, rs);
   2311         addiu(scratch, scratch, -1);
   2312         bgezal(scratch, offset);
   2313         break;
   2314       case Ugreater_equal:
   2315         sltu(scratch, rs, r2);
   2316         addiu(scratch, scratch, -1);
   2317         bltzal(scratch, offset);
   2318         break;
   2319       case Uless:
   2320         sltu(scratch, rs, r2);
   2321         addiu(scratch, scratch, -1);
   2322         bgezal(scratch, offset);
   2323         break;
   2324       case Uless_equal:
   2325         sltu(scratch, r2, rs);
   2326         addiu(scratch, scratch, -1);
   2327         bltzal(scratch, offset);
   2328         break;
   2329 
   2330       default:
   2331         UNREACHABLE();
   2332     }
   2333   }
   2334   // Emit a nop in the branch delay slot if required.
   2335   if (bdslot == PROTECT)
   2336     nop();
   2337 }
   2338 
   2339 
   2340 void MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) {
   2341   bal(shifted_branch_offset(L, false));
   2342 
   2343   // Emit a nop in the branch delay slot if required.
   2344   if (bdslot == PROTECT)
   2345     nop();
   2346 }
   2347 
   2348 
   2349 void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs,
   2350                                         const Operand& rt,
   2351                                         BranchDelaySlot bdslot) {
   2352   BRANCH_ARGS_CHECK(cond, rs, rt);
   2353 
   2354   int32_t offset = 0;
   2355   Register r2 = no_reg;
   2356   Register scratch = at;
   2357   if (rt.is_reg()) {
   2358     r2 = rt.rm_;
   2359   } else if (cond != cc_always) {
   2360     r2 = scratch;
   2361     li(r2, rt);
   2362   }
   2363 
   2364   {
   2365     BlockTrampolinePoolScope block_trampoline_pool(this);
   2366     switch (cond) {
   2367       case cc_always:
   2368         offset = shifted_branch_offset(L, false);
   2369         bal(offset);
   2370         break;
   2371       case eq:
   2372         bne(rs, r2, 2);
   2373         nop();
   2374         offset = shifted_branch_offset(L, false);
   2375         bal(offset);
   2376         break;
   2377       case ne:
   2378         beq(rs, r2, 2);
   2379         nop();
   2380         offset = shifted_branch_offset(L, false);
   2381         bal(offset);
   2382         break;
   2383 
   2384       // Signed comparison.
   2385       case greater:
   2386         slt(scratch, r2, rs);
   2387         addiu(scratch, scratch, -1);
   2388         offset = shifted_branch_offset(L, false);
   2389         bgezal(scratch, offset);
   2390         break;
   2391       case greater_equal:
   2392         slt(scratch, rs, r2);
   2393         addiu(scratch, scratch, -1);
   2394         offset = shifted_branch_offset(L, false);
   2395         bltzal(scratch, offset);
   2396         break;
   2397       case less:
   2398         slt(scratch, rs, r2);
   2399         addiu(scratch, scratch, -1);
   2400         offset = shifted_branch_offset(L, false);
   2401         bgezal(scratch, offset);
   2402         break;
   2403       case less_equal:
   2404         slt(scratch, r2, rs);
   2405         addiu(scratch, scratch, -1);
   2406         offset = shifted_branch_offset(L, false);
   2407         bltzal(scratch, offset);
   2408         break;
   2409 
   2410       // Unsigned comparison.
   2411       case Ugreater:
   2412         sltu(scratch, r2, rs);
   2413         addiu(scratch, scratch, -1);
   2414         offset = shifted_branch_offset(L, false);
   2415         bgezal(scratch, offset);
   2416         break;
   2417       case Ugreater_equal:
   2418         sltu(scratch, rs, r2);
   2419         addiu(scratch, scratch, -1);
   2420         offset = shifted_branch_offset(L, false);
   2421         bltzal(scratch, offset);
   2422         break;
   2423       case Uless:
   2424         sltu(scratch, rs, r2);
   2425         addiu(scratch, scratch, -1);
   2426         offset = shifted_branch_offset(L, false);
   2427         bgezal(scratch, offset);
   2428         break;
   2429       case Uless_equal:
   2430         sltu(scratch, r2, rs);
   2431         addiu(scratch, scratch, -1);
   2432         offset = shifted_branch_offset(L, false);
   2433         bltzal(scratch, offset);
   2434         break;
   2435 
   2436       default:
   2437         UNREACHABLE();
   2438     }
   2439   }
   2440   // Check that offset could actually hold on an int16_t.
   2441   ASSERT(is_int16(offset));
   2442 
   2443   // Emit a nop in the branch delay slot if required.
   2444   if (bdslot == PROTECT)
   2445     nop();
   2446 }
   2447 
   2448 
   2449 void MacroAssembler::Jump(Register target,
   2450                           Condition cond,
   2451                           Register rs,
   2452                           const Operand& rt,
   2453                           BranchDelaySlot bd) {
   2454   BlockTrampolinePoolScope block_trampoline_pool(this);
   2455   if (cond == cc_always) {
   2456     jr(target);
   2457   } else {
   2458     BRANCH_ARGS_CHECK(cond, rs, rt);
   2459     Branch(2, NegateCondition(cond), rs, rt);
   2460     jr(target);
   2461   }
   2462   // Emit a nop in the branch delay slot if required.
   2463   if (bd == PROTECT)
   2464     nop();
   2465 }
   2466 
   2467 
   2468 void MacroAssembler::Jump(intptr_t target,
   2469                           RelocInfo::Mode rmode,
   2470                           Condition cond,
   2471                           Register rs,
   2472                           const Operand& rt,
   2473                           BranchDelaySlot bd) {
   2474   Label skip;
   2475   if (cond != cc_always) {
   2476     Branch(USE_DELAY_SLOT, &skip, NegateCondition(cond), rs, rt);
   2477   }
   2478   // The first instruction of 'li' may be placed in the delay slot.
   2479   // This is not an issue, t9 is expected to be clobbered anyway.
   2480   li(t9, Operand(target, rmode));
   2481   Jump(t9, al, zero_reg, Operand(zero_reg), bd);
   2482   bind(&skip);
   2483 }
   2484 
   2485 
   2486 void MacroAssembler::Jump(Address target,
   2487                           RelocInfo::Mode rmode,
   2488                           Condition cond,
   2489                           Register rs,
   2490                           const Operand& rt,
   2491                           BranchDelaySlot bd) {
   2492   ASSERT(!RelocInfo::IsCodeTarget(rmode));
   2493   Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd);
   2494 }
   2495 
   2496 
   2497 void MacroAssembler::Jump(Handle<Code> code,
   2498                           RelocInfo::Mode rmode,
   2499                           Condition cond,
   2500                           Register rs,
   2501                           const Operand& rt,
   2502                           BranchDelaySlot bd) {
   2503   ASSERT(RelocInfo::IsCodeTarget(rmode));
   2504   AllowDeferredHandleDereference embedding_raw_address;
   2505   Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd);
   2506 }
   2507 
   2508 
   2509 int MacroAssembler::CallSize(Register target,
   2510                              Condition cond,
   2511                              Register rs,
   2512                              const Operand& rt,
   2513                              BranchDelaySlot bd) {
   2514   int size = 0;
   2515 
   2516   if (cond == cc_always) {
   2517     size += 1;
   2518   } else {
   2519     size += 3;
   2520   }
   2521 
   2522   if (bd == PROTECT)
   2523     size += 1;
   2524 
   2525   return size * kInstrSize;
   2526 }
   2527 
   2528 
   2529 // Note: To call gcc-compiled C code on mips, you must call thru t9.
   2530 void MacroAssembler::Call(Register target,
   2531                           Condition cond,
   2532                           Register rs,
   2533                           const Operand& rt,
   2534                           BranchDelaySlot bd) {
   2535   BlockTrampolinePoolScope block_trampoline_pool(this);
   2536   Label start;
   2537   bind(&start);
   2538   if (cond == cc_always) {
   2539     jalr(target);
   2540   } else {
   2541     BRANCH_ARGS_CHECK(cond, rs, rt);
   2542     Branch(2, NegateCondition(cond), rs, rt);
   2543     jalr(target);
   2544   }
   2545   // Emit a nop in the branch delay slot if required.
   2546   if (bd == PROTECT)
   2547     nop();
   2548 
   2549   ASSERT_EQ(CallSize(target, cond, rs, rt, bd),
   2550             SizeOfCodeGeneratedSince(&start));
   2551 }
   2552 
   2553 
   2554 int MacroAssembler::CallSize(Address target,
   2555                              RelocInfo::Mode rmode,
   2556                              Condition cond,
   2557                              Register rs,
   2558                              const Operand& rt,
   2559                              BranchDelaySlot bd) {
   2560   int size = CallSize(t9, cond, rs, rt, bd);
   2561   return size + 2 * kInstrSize;
   2562 }
   2563 
   2564 
   2565 void MacroAssembler::Call(Address target,
   2566                           RelocInfo::Mode rmode,
   2567                           Condition cond,
   2568                           Register rs,
   2569                           const Operand& rt,
   2570                           BranchDelaySlot bd) {
   2571   BlockTrampolinePoolScope block_trampoline_pool(this);
   2572   Label start;
   2573   bind(&start);
   2574   int32_t target_int = reinterpret_cast<int32_t>(target);
   2575   // Must record previous source positions before the
   2576   // li() generates a new code target.
   2577   positions_recorder()->WriteRecordedPositions();
   2578   li(t9, Operand(target_int, rmode), CONSTANT_SIZE);
   2579   Call(t9, cond, rs, rt, bd);
   2580   ASSERT_EQ(CallSize(target, rmode, cond, rs, rt, bd),
   2581             SizeOfCodeGeneratedSince(&start));
   2582 }
   2583 
   2584 
   2585 int MacroAssembler::CallSize(Handle<Code> code,
   2586                              RelocInfo::Mode rmode,
   2587                              TypeFeedbackId ast_id,
   2588                              Condition cond,
   2589                              Register rs,
   2590                              const Operand& rt,
   2591                              BranchDelaySlot bd) {
   2592   AllowDeferredHandleDereference using_raw_address;
   2593   return CallSize(reinterpret_cast<Address>(code.location()),
   2594       rmode, cond, rs, rt, bd);
   2595 }
   2596 
   2597 
   2598 void MacroAssembler::Call(Handle<Code> code,
   2599                           RelocInfo::Mode rmode,
   2600                           TypeFeedbackId ast_id,
   2601                           Condition cond,
   2602                           Register rs,
   2603                           const Operand& rt,
   2604                           BranchDelaySlot bd) {
   2605   BlockTrampolinePoolScope block_trampoline_pool(this);
   2606   Label start;
   2607   bind(&start);
   2608   ASSERT(RelocInfo::IsCodeTarget(rmode));
   2609   if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
   2610     SetRecordedAstId(ast_id);
   2611     rmode = RelocInfo::CODE_TARGET_WITH_ID;
   2612   }
   2613   AllowDeferredHandleDereference embedding_raw_address;
   2614   Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd);
   2615   ASSERT_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd),
   2616             SizeOfCodeGeneratedSince(&start));
   2617 }
   2618 
   2619 
   2620 void MacroAssembler::Ret(Condition cond,
   2621                          Register rs,
   2622                          const Operand& rt,
   2623                          BranchDelaySlot bd) {
   2624   Jump(ra, cond, rs, rt, bd);
   2625 }
   2626 
   2627 
   2628 void MacroAssembler::J(Label* L, BranchDelaySlot bdslot) {
   2629   BlockTrampolinePoolScope block_trampoline_pool(this);
   2630 
   2631   uint32_t imm28;
   2632   imm28 = jump_address(L);
   2633   imm28 &= kImm28Mask;
   2634   { BlockGrowBufferScope block_buf_growth(this);
   2635     // Buffer growth (and relocation) must be blocked for internal references
   2636     // until associated instructions are emitted and available to be patched.
   2637     RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
   2638     j(imm28);
   2639   }
   2640   // Emit a nop in the branch delay slot if required.
   2641   if (bdslot == PROTECT)
   2642     nop();
   2643 }
   2644 
   2645 
   2646 void MacroAssembler::Jr(Label* L, BranchDelaySlot bdslot) {
   2647   BlockTrampolinePoolScope block_trampoline_pool(this);
   2648 
   2649   uint32_t imm32;
   2650   imm32 = jump_address(L);
   2651   { BlockGrowBufferScope block_buf_growth(this);
   2652     // Buffer growth (and relocation) must be blocked for internal references
   2653     // until associated instructions are emitted and available to be patched.
   2654     RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
   2655     lui(at, (imm32 & kHiMask) >> kLuiShift);
   2656     ori(at, at, (imm32 & kImm16Mask));
   2657   }
   2658   jr(at);
   2659 
   2660   // Emit a nop in the branch delay slot if required.
   2661   if (bdslot == PROTECT)
   2662     nop();
   2663 }
   2664 
   2665 
   2666 void MacroAssembler::Jalr(Label* L, BranchDelaySlot bdslot) {
   2667   BlockTrampolinePoolScope block_trampoline_pool(this);
   2668 
   2669   uint32_t imm32;
   2670   imm32 = jump_address(L);
   2671   { BlockGrowBufferScope block_buf_growth(this);
   2672     // Buffer growth (and relocation) must be blocked for internal references
   2673     // until associated instructions are emitted and available to be patched.
   2674     RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
   2675     lui(at, (imm32 & kHiMask) >> kLuiShift);
   2676     ori(at, at, (imm32 & kImm16Mask));
   2677   }
   2678   jalr(at);
   2679 
   2680   // Emit a nop in the branch delay slot if required.
   2681   if (bdslot == PROTECT)
   2682     nop();
   2683 }
   2684 
   2685 
   2686 void MacroAssembler::DropAndRet(int drop) {
   2687   Ret(USE_DELAY_SLOT);
   2688   addiu(sp, sp, drop * kPointerSize);
   2689 }
   2690 
   2691 void MacroAssembler::DropAndRet(int drop,
   2692                                 Condition cond,
   2693                                 Register r1,
   2694                                 const Operand& r2) {
   2695   // Both Drop and Ret need to be conditional.
   2696   Label skip;
   2697   if (cond != cc_always) {
   2698     Branch(&skip, NegateCondition(cond), r1, r2);
   2699   }
   2700 
   2701   Drop(drop);
   2702   Ret();
   2703 
   2704   if (cond != cc_always) {
   2705     bind(&skip);
   2706   }
   2707 }
   2708 
   2709 
   2710 void MacroAssembler::Drop(int count,
   2711                           Condition cond,
   2712                           Register reg,
   2713                           const Operand& op) {
   2714   if (count <= 0) {
   2715     return;
   2716   }
   2717 
   2718   Label skip;
   2719 
   2720   if (cond != al) {
   2721      Branch(&skip, NegateCondition(cond), reg, op);
   2722   }
   2723 
   2724   addiu(sp, sp, count * kPointerSize);
   2725 
   2726   if (cond != al) {
   2727     bind(&skip);
   2728   }
   2729 }
   2730 
   2731 
   2732 
   2733 void MacroAssembler::Swap(Register reg1,
   2734                           Register reg2,
   2735                           Register scratch) {
   2736   if (scratch.is(no_reg)) {
   2737     Xor(reg1, reg1, Operand(reg2));
   2738     Xor(reg2, reg2, Operand(reg1));
   2739     Xor(reg1, reg1, Operand(reg2));
   2740   } else {
   2741     mov(scratch, reg1);
   2742     mov(reg1, reg2);
   2743     mov(reg2, scratch);
   2744   }
   2745 }
   2746 
   2747 
   2748 void MacroAssembler::Call(Label* target) {
   2749   BranchAndLink(target);
   2750 }
   2751 
   2752 
   2753 void MacroAssembler::Push(Handle<Object> handle) {
   2754   li(at, Operand(handle));
   2755   push(at);
   2756 }
   2757 
   2758 
   2759 void MacroAssembler::DebugBreak() {
   2760   PrepareCEntryArgs(0);
   2761   PrepareCEntryFunction(ExternalReference(Runtime::kDebugBreak, isolate()));
   2762   CEntryStub ces(isolate(), 1);
   2763   ASSERT(AllowThisStubCall(&ces));
   2764   Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
   2765 }
   2766 
   2767 
   2768 // ---------------------------------------------------------------------------
   2769 // Exception handling.
   2770 
   2771 void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
   2772                                     int handler_index) {
   2773   // Adjust this code if not the case.
   2774   STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
   2775   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
   2776   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
   2777   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
   2778   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   2779   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
   2780 
   2781   // For the JSEntry handler, we must preserve a0-a3 and s0.
   2782   // t1-t3 are available. We will build up the handler from the bottom by
   2783   // pushing on the stack.
   2784   // Set up the code object (t1) and the state (t2) for pushing.
   2785   unsigned state =
   2786       StackHandler::IndexField::encode(handler_index) |
   2787       StackHandler::KindField::encode(kind);
   2788   li(t1, Operand(CodeObject()), CONSTANT_SIZE);
   2789   li(t2, Operand(state));
   2790 
   2791   // Push the frame pointer, context, state, and code object.
   2792   if (kind == StackHandler::JS_ENTRY) {
   2793     ASSERT_EQ(Smi::FromInt(0), 0);
   2794     // The second zero_reg indicates no context.
   2795     // The first zero_reg is the NULL frame pointer.
   2796     // The operands are reversed to match the order of MultiPush/Pop.
   2797     Push(zero_reg, zero_reg, t2, t1);
   2798   } else {
   2799     MultiPush(t1.bit() | t2.bit() | cp.bit() | fp.bit());
   2800   }
   2801 
   2802   // Link the current handler as the next handler.
   2803   li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
   2804   lw(t1, MemOperand(t2));
   2805   push(t1);
   2806   // Set this new handler as the current one.
   2807   sw(sp, MemOperand(t2));
   2808 }
   2809 
   2810 
   2811 void MacroAssembler::PopTryHandler() {
   2812   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   2813   pop(a1);
   2814   Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
   2815   li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
   2816   sw(a1, MemOperand(at));
   2817 }
   2818 
   2819 
   2820 void MacroAssembler::JumpToHandlerEntry() {
   2821   // Compute the handler entry address and jump to it.  The handler table is
   2822   // a fixed array of (smi-tagged) code offsets.
   2823   // v0 = exception, a1 = code object, a2 = state.
   2824   lw(a3, FieldMemOperand(a1, Code::kHandlerTableOffset));  // Handler table.
   2825   Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   2826   srl(a2, a2, StackHandler::kKindWidth);  // Handler index.
   2827   sll(a2, a2, kPointerSizeLog2);
   2828   Addu(a2, a3, a2);
   2829   lw(a2, MemOperand(a2));  // Smi-tagged offset.
   2830   Addu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));  // Code start.
   2831   sra(t9, a2, kSmiTagSize);
   2832   Addu(t9, t9, a1);
   2833   Jump(t9);  // Jump.
   2834 }
   2835 
   2836 
   2837 void MacroAssembler::Throw(Register value) {
   2838   // Adjust this code if not the case.
   2839   STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
   2840   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   2841   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
   2842   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
   2843   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   2844   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
   2845 
   2846   // The exception is expected in v0.
   2847   Move(v0, value);
   2848 
   2849   // Drop the stack pointer to the top of the top handler.
   2850   li(a3, Operand(ExternalReference(Isolate::kHandlerAddress,
   2851                                    isolate())));
   2852   lw(sp, MemOperand(a3));
   2853 
   2854   // Restore the next handler.
   2855   pop(a2);
   2856   sw(a2, MemOperand(a3));
   2857 
   2858   // Get the code object (a1) and state (a2).  Restore the context and frame
   2859   // pointer.
   2860   MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit());
   2861 
   2862   // If the handler is a JS frame, restore the context to the frame.
   2863   // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
   2864   // or cp.
   2865   Label done;
   2866   Branch(&done, eq, cp, Operand(zero_reg));
   2867   sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   2868   bind(&done);
   2869 
   2870   JumpToHandlerEntry();
   2871 }
   2872 
   2873 
   2874 void MacroAssembler::ThrowUncatchable(Register value) {
   2875   // Adjust this code if not the case.
   2876   STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
   2877   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
   2878   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
   2879   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
   2880   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   2881   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
   2882 
   2883   // The exception is expected in v0.
   2884   if (!value.is(v0)) {
   2885     mov(v0, value);
   2886   }
   2887   // Drop the stack pointer to the top of the top stack handler.
   2888   li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
   2889   lw(sp, MemOperand(a3));
   2890 
   2891   // Unwind the handlers until the ENTRY handler is found.
   2892   Label fetch_next, check_kind;
   2893   jmp(&check_kind);
   2894   bind(&fetch_next);
   2895   lw(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
   2896 
   2897   bind(&check_kind);
   2898   STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
   2899   lw(a2, MemOperand(sp, StackHandlerConstants::kStateOffset));
   2900   And(a2, a2, Operand(StackHandler::KindField::kMask));
   2901   Branch(&fetch_next, ne, a2, Operand(zero_reg));
   2902 
   2903   // Set the top handler address to next handler past the top ENTRY handler.
   2904   pop(a2);
   2905   sw(a2, MemOperand(a3));
   2906 
   2907   // Get the code object (a1) and state (a2).  Clear the context and frame
   2908   // pointer (0 was saved in the handler).
   2909   MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit());
   2910 
   2911   JumpToHandlerEntry();
   2912 }
   2913 
   2914 
   2915 void MacroAssembler::Allocate(int object_size,
   2916                               Register result,
   2917                               Register scratch1,
   2918                               Register scratch2,
   2919                               Label* gc_required,
   2920                               AllocationFlags flags) {
   2921   ASSERT(object_size <= Page::kMaxRegularHeapObjectSize);
   2922   if (!FLAG_inline_new) {
   2923     if (emit_debug_code()) {
   2924       // Trash the registers to simulate an allocation failure.
   2925       li(result, 0x7091);
   2926       li(scratch1, 0x7191);
   2927       li(scratch2, 0x7291);
   2928     }
   2929     jmp(gc_required);
   2930     return;
   2931   }
   2932 
   2933   ASSERT(!result.is(scratch1));
   2934   ASSERT(!result.is(scratch2));
   2935   ASSERT(!scratch1.is(scratch2));
   2936   ASSERT(!scratch1.is(t9));
   2937   ASSERT(!scratch2.is(t9));
   2938   ASSERT(!result.is(t9));
   2939 
   2940   // Make object size into bytes.
   2941   if ((flags & SIZE_IN_WORDS) != 0) {
   2942     object_size *= kPointerSize;
   2943   }
   2944   ASSERT_EQ(0, object_size & kObjectAlignmentMask);
   2945 
   2946   // Check relative positions of allocation top and limit addresses.
   2947   // ARM adds additional checks to make sure the ldm instruction can be
   2948   // used. On MIPS we don't have ldm so we don't need additional checks either.
   2949   ExternalReference allocation_top =
   2950       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   2951   ExternalReference allocation_limit =
   2952       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   2953 
   2954   intptr_t top   =
   2955       reinterpret_cast<intptr_t>(allocation_top.address());
   2956   intptr_t limit =
   2957       reinterpret_cast<intptr_t>(allocation_limit.address());
   2958   ASSERT((limit - top) == kPointerSize);
   2959 
   2960   // Set up allocation top address and object size registers.
   2961   Register topaddr = scratch1;
   2962   li(topaddr, Operand(allocation_top));
   2963 
   2964   // This code stores a temporary value in t9.
   2965   if ((flags & RESULT_CONTAINS_TOP) == 0) {
   2966     // Load allocation top into result and allocation limit into t9.
   2967     lw(result, MemOperand(topaddr));
   2968     lw(t9, MemOperand(topaddr, kPointerSize));
   2969   } else {
   2970     if (emit_debug_code()) {
   2971       // Assert that result actually contains top on entry. t9 is used
   2972       // immediately below so this use of t9 does not cause difference with
   2973       // respect to register content between debug and release mode.
   2974       lw(t9, MemOperand(topaddr));
   2975       Check(eq, kUnexpectedAllocationTop, result, Operand(t9));
   2976     }
   2977     // Load allocation limit into t9. Result already contains allocation top.
   2978     lw(t9, MemOperand(topaddr, limit - top));
   2979   }
   2980 
   2981   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   2982     // Align the next allocation. Storing the filler map without checking top is
   2983     // safe in new-space because the limit of the heap is aligned there.
   2984     ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
   2985     ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   2986     And(scratch2, result, Operand(kDoubleAlignmentMask));
   2987     Label aligned;
   2988     Branch(&aligned, eq, scratch2, Operand(zero_reg));
   2989     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
   2990       Branch(gc_required, Ugreater_equal, result, Operand(t9));
   2991     }
   2992     li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
   2993     sw(scratch2, MemOperand(result));
   2994     Addu(result, result, Operand(kDoubleSize / 2));
   2995     bind(&aligned);
   2996   }
   2997 
   2998   // Calculate new top and bail out if new space is exhausted. Use result
   2999   // to calculate the new top.
   3000   Addu(scratch2, result, Operand(object_size));
   3001   Branch(gc_required, Ugreater, scratch2, Operand(t9));
   3002   sw(scratch2, MemOperand(topaddr));
   3003 
   3004   // Tag object if requested.
   3005   if ((flags & TAG_OBJECT) != 0) {
   3006     Addu(result, result, Operand(kHeapObjectTag));
   3007   }
   3008 }
   3009 
   3010 
   3011 void MacroAssembler::Allocate(Register object_size,
   3012                               Register result,
   3013                               Register scratch1,
   3014                               Register scratch2,
   3015                               Label* gc_required,
   3016                               AllocationFlags flags) {
   3017   if (!FLAG_inline_new) {
   3018     if (emit_debug_code()) {
   3019       // Trash the registers to simulate an allocation failure.
   3020       li(result, 0x7091);
   3021       li(scratch1, 0x7191);
   3022       li(scratch2, 0x7291);
   3023     }
   3024     jmp(gc_required);
   3025     return;
   3026   }
   3027 
   3028   ASSERT(!result.is(scratch1));
   3029   ASSERT(!result.is(scratch2));
   3030   ASSERT(!scratch1.is(scratch2));
   3031   ASSERT(!object_size.is(t9));
   3032   ASSERT(!scratch1.is(t9) && !scratch2.is(t9) && !result.is(t9));
   3033 
   3034   // Check relative positions of allocation top and limit addresses.
   3035   // ARM adds additional checks to make sure the ldm instruction can be
   3036   // used. On MIPS we don't have ldm so we don't need additional checks either.
   3037   ExternalReference allocation_top =
   3038       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   3039   ExternalReference allocation_limit =
   3040       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   3041   intptr_t top   =
   3042       reinterpret_cast<intptr_t>(allocation_top.address());
   3043   intptr_t limit =
   3044       reinterpret_cast<intptr_t>(allocation_limit.address());
   3045   ASSERT((limit - top) == kPointerSize);
   3046 
   3047   // Set up allocation top address and object size registers.
   3048   Register topaddr = scratch1;
   3049   li(topaddr, Operand(allocation_top));
   3050 
   3051   // This code stores a temporary value in t9.
   3052   if ((flags & RESULT_CONTAINS_TOP) == 0) {
   3053     // Load allocation top into result and allocation limit into t9.
   3054     lw(result, MemOperand(topaddr));
   3055     lw(t9, MemOperand(topaddr, kPointerSize));
   3056   } else {
   3057     if (emit_debug_code()) {
   3058       // Assert that result actually contains top on entry. t9 is used
   3059       // immediately below so this use of t9 does not cause difference with
   3060       // respect to register content between debug and release mode.
   3061       lw(t9, MemOperand(topaddr));
   3062       Check(eq, kUnexpectedAllocationTop, result, Operand(t9));
   3063     }
   3064     // Load allocation limit into t9. Result already contains allocation top.
   3065     lw(t9, MemOperand(topaddr, limit - top));
   3066   }
   3067 
   3068   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   3069     // Align the next allocation. Storing the filler map without checking top is
   3070     // safe in new-space because the limit of the heap is aligned there.
   3071     ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
   3072     ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   3073     And(scratch2, result, Operand(kDoubleAlignmentMask));
   3074     Label aligned;
   3075     Branch(&aligned, eq, scratch2, Operand(zero_reg));
   3076     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
   3077       Branch(gc_required, Ugreater_equal, result, Operand(t9));
   3078     }
   3079     li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
   3080     sw(scratch2, MemOperand(result));
   3081     Addu(result, result, Operand(kDoubleSize / 2));
   3082     bind(&aligned);
   3083   }
   3084 
   3085   // Calculate new top and bail out if new space is exhausted. Use result
   3086   // to calculate the new top. Object size may be in words so a shift is
   3087   // required to get the number of bytes.
   3088   if ((flags & SIZE_IN_WORDS) != 0) {
   3089     sll(scratch2, object_size, kPointerSizeLog2);
   3090     Addu(scratch2, result, scratch2);
   3091   } else {
   3092     Addu(scratch2, result, Operand(object_size));
   3093   }
   3094   Branch(gc_required, Ugreater, scratch2, Operand(t9));
   3095 
   3096   // Update allocation top. result temporarily holds the new top.
   3097   if (emit_debug_code()) {
   3098     And(t9, scratch2, Operand(kObjectAlignmentMask));
   3099     Check(eq, kUnalignedAllocationInNewSpace, t9, Operand(zero_reg));
   3100   }
   3101   sw(scratch2, MemOperand(topaddr));
   3102 
   3103   // Tag object if requested.
   3104   if ((flags & TAG_OBJECT) != 0) {
   3105     Addu(result, result, Operand(kHeapObjectTag));
   3106   }
   3107 }
   3108 
   3109 
   3110 void MacroAssembler::UndoAllocationInNewSpace(Register object,
   3111                                               Register scratch) {
   3112   ExternalReference new_space_allocation_top =
   3113       ExternalReference::new_space_allocation_top_address(isolate());
   3114 
   3115   // Make sure the object has no tag before resetting top.
   3116   And(object, object, Operand(~kHeapObjectTagMask));
   3117 #ifdef DEBUG
   3118   // Check that the object un-allocated is below the current top.
   3119   li(scratch, Operand(new_space_allocation_top));
   3120   lw(scratch, MemOperand(scratch));
   3121   Check(less, kUndoAllocationOfNonAllocatedMemory,
   3122       object, Operand(scratch));
   3123 #endif
   3124   // Write the address of the object to un-allocate as the current top.
   3125   li(scratch, Operand(new_space_allocation_top));
   3126   sw(object, MemOperand(scratch));
   3127 }
   3128 
   3129 
   3130 void MacroAssembler::AllocateTwoByteString(Register result,
   3131                                            Register length,
   3132                                            Register scratch1,
   3133                                            Register scratch2,
   3134                                            Register scratch3,
   3135                                            Label* gc_required) {
   3136   // Calculate the number of bytes needed for the characters in the string while
   3137   // observing object alignment.
   3138   ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
   3139   sll(scratch1, length, 1);  // Length in bytes, not chars.
   3140   addiu(scratch1, scratch1,
   3141        kObjectAlignmentMask + SeqTwoByteString::kHeaderSize);
   3142   And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
   3143 
   3144   // Allocate two-byte string in new space.
   3145   Allocate(scratch1,
   3146            result,
   3147            scratch2,
   3148            scratch3,
   3149            gc_required,
   3150            TAG_OBJECT);
   3151 
   3152   // Set the map, length and hash field.
   3153   InitializeNewString(result,
   3154                       length,
   3155                       Heap::kStringMapRootIndex,
   3156                       scratch1,
   3157                       scratch2);
   3158 }
   3159 
   3160 
   3161 void MacroAssembler::AllocateAsciiString(Register result,
   3162                                          Register length,
   3163                                          Register scratch1,
   3164                                          Register scratch2,
   3165                                          Register scratch3,
   3166                                          Label* gc_required) {
   3167   // Calculate the number of bytes needed for the characters in the string
   3168   // while observing object alignment.
   3169   ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
   3170   ASSERT(kCharSize == 1);
   3171   addiu(scratch1, length, kObjectAlignmentMask + SeqOneByteString::kHeaderSize);
   3172   And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
   3173 
   3174   // Allocate ASCII string in new space.
   3175   Allocate(scratch1,
   3176            result,
   3177            scratch2,
   3178            scratch3,
   3179            gc_required,
   3180            TAG_OBJECT);
   3181 
   3182   // Set the map, length and hash field.
   3183   InitializeNewString(result,
   3184                       length,
   3185                       Heap::kAsciiStringMapRootIndex,
   3186                       scratch1,
   3187                       scratch2);
   3188 }
   3189 
   3190 
   3191 void MacroAssembler::AllocateTwoByteConsString(Register result,
   3192                                                Register length,
   3193                                                Register scratch1,
   3194                                                Register scratch2,
   3195                                                Label* gc_required) {
   3196   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
   3197            TAG_OBJECT);
   3198   InitializeNewString(result,
   3199                       length,
   3200                       Heap::kConsStringMapRootIndex,
   3201                       scratch1,
   3202                       scratch2);
   3203 }
   3204 
   3205 
   3206 void MacroAssembler::AllocateAsciiConsString(Register result,
   3207                                              Register length,
   3208                                              Register scratch1,
   3209                                              Register scratch2,
   3210                                              Label* gc_required) {
   3211   Allocate(ConsString::kSize,
   3212            result,
   3213            scratch1,
   3214            scratch2,
   3215            gc_required,
   3216            TAG_OBJECT);
   3217 
   3218   InitializeNewString(result,
   3219                       length,
   3220                       Heap::kConsAsciiStringMapRootIndex,
   3221                       scratch1,
   3222                       scratch2);
   3223 }
   3224 
   3225 
   3226 void MacroAssembler::AllocateTwoByteSlicedString(Register result,
   3227                                                  Register length,
   3228                                                  Register scratch1,
   3229                                                  Register scratch2,
   3230                                                  Label* gc_required) {
   3231   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
   3232            TAG_OBJECT);
   3233 
   3234   InitializeNewString(result,
   3235                       length,
   3236                       Heap::kSlicedStringMapRootIndex,
   3237                       scratch1,
   3238                       scratch2);
   3239 }
   3240 
   3241 
   3242 void MacroAssembler::AllocateAsciiSlicedString(Register result,
   3243                                                Register length,
   3244                                                Register scratch1,
   3245                                                Register scratch2,
   3246                                                Label* gc_required) {
   3247   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
   3248            TAG_OBJECT);
   3249 
   3250   InitializeNewString(result,
   3251                       length,
   3252                       Heap::kSlicedAsciiStringMapRootIndex,
   3253                       scratch1,
   3254                       scratch2);
   3255 }
   3256 
   3257 
   3258 void MacroAssembler::JumpIfNotUniqueName(Register reg,
   3259                                          Label* not_unique_name) {
   3260   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
   3261   Label succeed;
   3262   And(at, reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
   3263   Branch(&succeed, eq, at, Operand(zero_reg));
   3264   Branch(not_unique_name, ne, reg, Operand(SYMBOL_TYPE));
   3265 
   3266   bind(&succeed);
   3267 }
   3268 
   3269 
   3270 // Allocates a heap number or jumps to the label if the young space is full and
   3271 // a scavenge is needed.
   3272 void MacroAssembler::AllocateHeapNumber(Register result,
   3273                                         Register scratch1,
   3274                                         Register scratch2,
   3275                                         Register heap_number_map,
   3276                                         Label* need_gc,
   3277                                         TaggingMode tagging_mode) {
   3278   // Allocate an object in the heap for the heap number and tag it as a heap
   3279   // object.
   3280   Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc,
   3281            tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
   3282 
   3283   // Store heap number map in the allocated object.
   3284   AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
   3285   if (tagging_mode == TAG_RESULT) {
   3286     sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
   3287   } else {
   3288     sw(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
   3289   }
   3290 }
   3291 
   3292 
   3293 void MacroAssembler::AllocateHeapNumberWithValue(Register result,
   3294                                                  FPURegister value,
   3295                                                  Register scratch1,
   3296                                                  Register scratch2,
   3297                                                  Label* gc_required) {
   3298   LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
   3299   AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required);
   3300   sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset));
   3301 }
   3302 
   3303 
   3304 // Copies a fixed number of fields of heap objects from src to dst.
   3305 void MacroAssembler::CopyFields(Register dst,
   3306                                 Register src,
   3307                                 RegList temps,
   3308                                 int field_count) {
   3309   ASSERT((temps & dst.bit()) == 0);
   3310   ASSERT((temps & src.bit()) == 0);
   3311   // Primitive implementation using only one temporary register.
   3312 
   3313   Register tmp = no_reg;
   3314   // Find a temp register in temps list.
   3315   for (int i = 0; i < kNumRegisters; i++) {
   3316     if ((temps & (1 << i)) != 0) {
   3317       tmp.code_ = i;
   3318       break;
   3319     }
   3320   }
   3321   ASSERT(!tmp.is(no_reg));
   3322 
   3323   for (int i = 0; i < field_count; i++) {
   3324     lw(tmp, FieldMemOperand(src, i * kPointerSize));
   3325     sw(tmp, FieldMemOperand(dst, i * kPointerSize));
   3326   }
   3327 }
   3328 
   3329 
   3330 void MacroAssembler::CopyBytes(Register src,
   3331                                Register dst,
   3332                                Register length,
   3333                                Register scratch) {
   3334   Label align_loop_1, word_loop, byte_loop, byte_loop_1, done;
   3335 
   3336   // Align src before copying in word size chunks.
   3337   Branch(&byte_loop, le, length, Operand(kPointerSize));
   3338   bind(&align_loop_1);
   3339   And(scratch, src, kPointerSize - 1);
   3340   Branch(&word_loop, eq, scratch, Operand(zero_reg));
   3341   lbu(scratch, MemOperand(src));
   3342   Addu(src, src, 1);
   3343   sb(scratch, MemOperand(dst));
   3344   Addu(dst, dst, 1);
   3345   Subu(length, length, Operand(1));
   3346   Branch(&align_loop_1, ne, length, Operand(zero_reg));
   3347 
   3348   // Copy bytes in word size chunks.
   3349   bind(&word_loop);
   3350   if (emit_debug_code()) {
   3351     And(scratch, src, kPointerSize - 1);
   3352     Assert(eq, kExpectingAlignmentForCopyBytes,
   3353         scratch, Operand(zero_reg));
   3354   }
   3355   Branch(&byte_loop, lt, length, Operand(kPointerSize));
   3356   lw(scratch, MemOperand(src));
   3357   Addu(src, src, kPointerSize);
   3358 
   3359   // TODO(kalmard) check if this can be optimized to use sw in most cases.
   3360   // Can't use unaligned access - copy byte by byte.
   3361   if (kArchEndian == kLittle) {
   3362     sb(scratch, MemOperand(dst, 0));
   3363     srl(scratch, scratch, 8);
   3364     sb(scratch, MemOperand(dst, 1));
   3365     srl(scratch, scratch, 8);
   3366     sb(scratch, MemOperand(dst, 2));
   3367     srl(scratch, scratch, 8);
   3368     sb(scratch, MemOperand(dst, 3));
   3369   } else {
   3370     sb(scratch, MemOperand(dst, 3));
   3371     srl(scratch, scratch, 8);
   3372     sb(scratch, MemOperand(dst, 2));
   3373     srl(scratch, scratch, 8);
   3374     sb(scratch, MemOperand(dst, 1));
   3375     srl(scratch, scratch, 8);
   3376     sb(scratch, MemOperand(dst, 0));
   3377   }
   3378 
   3379   Addu(dst, dst, 4);
   3380 
   3381   Subu(length, length, Operand(kPointerSize));
   3382   Branch(&word_loop);
   3383 
   3384   // Copy the last bytes if any left.
   3385   bind(&byte_loop);
   3386   Branch(&done, eq, length, Operand(zero_reg));
   3387   bind(&byte_loop_1);
   3388   lbu(scratch, MemOperand(src));
   3389   Addu(src, src, 1);
   3390   sb(scratch, MemOperand(dst));
   3391   Addu(dst, dst, 1);
   3392   Subu(length, length, Operand(1));
   3393   Branch(&byte_loop_1, ne, length, Operand(zero_reg));
   3394   bind(&done);
   3395 }
   3396 
   3397 
   3398 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
   3399                                                 Register end_offset,
   3400                                                 Register filler) {
   3401   Label loop, entry;
   3402   Branch(&entry);
   3403   bind(&loop);
   3404   sw(filler, MemOperand(start_offset));
   3405   Addu(start_offset, start_offset, kPointerSize);
   3406   bind(&entry);
   3407   Branch(&loop, lt, start_offset, Operand(end_offset));
   3408 }
   3409 
   3410 
   3411 void MacroAssembler::CheckFastElements(Register map,
   3412                                        Register scratch,
   3413                                        Label* fail) {
   3414   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
   3415   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
   3416   STATIC_ASSERT(FAST_ELEMENTS == 2);
   3417   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
   3418   lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
   3419   Branch(fail, hi, scratch,
   3420          Operand(Map::kMaximumBitField2FastHoleyElementValue));
   3421 }
   3422 
   3423 
   3424 void MacroAssembler::CheckFastObjectElements(Register map,
   3425                                              Register scratch,
   3426                                              Label* fail) {
   3427   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
   3428   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
   3429   STATIC_ASSERT(FAST_ELEMENTS == 2);
   3430   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
   3431   lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
   3432   Branch(fail, ls, scratch,
   3433          Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
   3434   Branch(fail, hi, scratch,
   3435          Operand(Map::kMaximumBitField2FastHoleyElementValue));
   3436 }
   3437 
   3438 
   3439 void MacroAssembler::CheckFastSmiElements(Register map,
   3440                                           Register scratch,
   3441                                           Label* fail) {
   3442   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
   3443   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
   3444   lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset));
   3445   Branch(fail, hi, scratch,
   3446          Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
   3447 }
   3448 
   3449 
   3450 void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
   3451                                                  Register key_reg,
   3452                                                  Register elements_reg,
   3453                                                  Register scratch1,
   3454                                                  Register scratch2,
   3455                                                  Register scratch3,
   3456                                                  Label* fail,
   3457                                                  int elements_offset) {
   3458   Label smi_value, maybe_nan, have_double_value, is_nan, done;
   3459   Register mantissa_reg = scratch2;
   3460   Register exponent_reg = scratch3;
   3461 
   3462   // Handle smi values specially.
   3463   JumpIfSmi(value_reg, &smi_value);
   3464 
   3465   // Ensure that the object is a heap number
   3466   CheckMap(value_reg,
   3467            scratch1,
   3468            Heap::kHeapNumberMapRootIndex,
   3469            fail,
   3470            DONT_DO_SMI_CHECK);
   3471 
   3472   // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
   3473   // in the exponent.
   3474   li(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32));
   3475   lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
   3476   Branch(&maybe_nan, ge, exponent_reg, Operand(scratch1));
   3477 
   3478   lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
   3479 
   3480   bind(&have_double_value);
   3481   sll(scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize);
   3482   Addu(scratch1, scratch1, elements_reg);
   3483   sw(mantissa_reg,
   3484       FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset
   3485           + kHoleNanLower32Offset));
   3486   sw(exponent_reg,
   3487       FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset
   3488           + kHoleNanUpper32Offset));
   3489   jmp(&done);
   3490 
   3491   bind(&maybe_nan);
   3492   // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
   3493   // it's an Infinity, and the non-NaN code path applies.
   3494   Branch(&is_nan, gt, exponent_reg, Operand(scratch1));
   3495   lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
   3496   Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg));
   3497   bind(&is_nan);
   3498   // Load canonical NaN for storing into the double array.
   3499   LoadRoot(at, Heap::kNanValueRootIndex);
   3500   lw(mantissa_reg, FieldMemOperand(at, HeapNumber::kMantissaOffset));
   3501   lw(exponent_reg, FieldMemOperand(at, HeapNumber::kExponentOffset));
   3502   jmp(&have_double_value);
   3503 
   3504   bind(&smi_value);
   3505   Addu(scratch1, elements_reg,
   3506       Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag -
   3507               elements_offset));
   3508   sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize);
   3509   Addu(scratch1, scratch1, scratch2);
   3510   // scratch1 is now effective address of the double element
   3511 
   3512   Register untagged_value = elements_reg;
   3513   SmiUntag(untagged_value, value_reg);
   3514   mtc1(untagged_value, f2);
   3515   cvt_d_w(f0, f2);
   3516   sdc1(f0, MemOperand(scratch1, 0));
   3517   bind(&done);
   3518 }
   3519 
   3520 
   3521 void MacroAssembler::CompareMapAndBranch(Register obj,
   3522                                          Register scratch,
   3523                                          Handle<Map> map,
   3524                                          Label* early_success,
   3525                                          Condition cond,
   3526                                          Label* branch_to) {
   3527   lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
   3528   CompareMapAndBranch(scratch, map, early_success, cond, branch_to);
   3529 }
   3530 
   3531 
   3532 void MacroAssembler::CompareMapAndBranch(Register obj_map,
   3533                                          Handle<Map> map,
   3534                                          Label* early_success,
   3535                                          Condition cond,
   3536                                          Label* branch_to) {
   3537   Branch(branch_to, cond, obj_map, Operand(map));
   3538 }
   3539 
   3540 
   3541 void MacroAssembler::CheckMap(Register obj,
   3542                               Register scratch,
   3543                               Handle<Map> map,
   3544                               Label* fail,
   3545                               SmiCheckType smi_check_type) {
   3546   if (smi_check_type == DO_SMI_CHECK) {
   3547     JumpIfSmi(obj, fail);
   3548   }
   3549   Label success;
   3550   CompareMapAndBranch(obj, scratch, map, &success, ne, fail);
   3551   bind(&success);
   3552 }
   3553 
   3554 
   3555 void MacroAssembler::DispatchMap(Register obj,
   3556                                  Register scratch,
   3557                                  Handle<Map> map,
   3558                                  Handle<Code> success,
   3559                                  SmiCheckType smi_check_type) {
   3560   Label fail;
   3561   if (smi_check_type == DO_SMI_CHECK) {
   3562     JumpIfSmi(obj, &fail);
   3563   }
   3564   lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
   3565   Jump(success, RelocInfo::CODE_TARGET, eq, scratch, Operand(map));
   3566   bind(&fail);
   3567 }
   3568 
   3569 
   3570 void MacroAssembler::CheckMap(Register obj,
   3571                               Register scratch,
   3572                               Heap::RootListIndex index,
   3573                               Label* fail,
   3574                               SmiCheckType smi_check_type) {
   3575   if (smi_check_type == DO_SMI_CHECK) {
   3576     JumpIfSmi(obj, fail);
   3577   }
   3578   lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
   3579   LoadRoot(at, index);
   3580   Branch(fail, ne, scratch, Operand(at));
   3581 }
   3582 
   3583 
   3584 void MacroAssembler::MovFromFloatResult(DoubleRegister dst) {
   3585   if (IsMipsSoftFloatABI) {
   3586     if (kArchEndian == kLittle) {
   3587       Move(dst, v0, v1);
   3588     } else {
   3589       Move(dst, v1, v0);
   3590     }
   3591   } else {
   3592     Move(dst, f0);  // Reg f0 is o32 ABI FP return value.
   3593   }
   3594 }
   3595 
   3596 
   3597 void MacroAssembler::MovFromFloatParameter(DoubleRegister dst) {
   3598   if (IsMipsSoftFloatABI) {
   3599     if (kArchEndian == kLittle) {
   3600       Move(dst, a0, a1);
   3601     } else {
   3602       Move(dst, a1, a0);
   3603     }
   3604   } else {
   3605     Move(dst, f12);  // Reg f12 is o32 ABI FP first argument value.
   3606   }
   3607 }
   3608 
   3609 
   3610 void MacroAssembler::MovToFloatParameter(DoubleRegister src) {
   3611   if (!IsMipsSoftFloatABI) {
   3612     Move(f12, src);
   3613   } else {
   3614     if (kArchEndian == kLittle) {
   3615       Move(a0, a1, src);
   3616     } else {
   3617       Move(a1, a0, src);
   3618     }
   3619   }
   3620 }
   3621 
   3622 
   3623 void MacroAssembler::MovToFloatResult(DoubleRegister src) {
   3624   if (!IsMipsSoftFloatABI) {
   3625     Move(f0, src);
   3626   } else {
   3627     if (kArchEndian == kLittle) {
   3628       Move(v0, v1, src);
   3629     } else {
   3630       Move(v1, v0, src);
   3631     }
   3632   }
   3633 }
   3634 
   3635 
   3636 void MacroAssembler::MovToFloatParameters(DoubleRegister src1,
   3637                                           DoubleRegister src2) {
   3638   if (!IsMipsSoftFloatABI) {
   3639     if (src2.is(f12)) {
   3640       ASSERT(!src1.is(f14));
   3641       Move(f14, src2);
   3642       Move(f12, src1);
   3643     } else {
   3644       Move(f12, src1);
   3645       Move(f14, src2);
   3646     }
   3647   } else {
   3648     if (kArchEndian == kLittle) {
   3649       Move(a0, a1, src1);
   3650       Move(a2, a3, src2);
   3651     } else {
   3652       Move(a1, a0, src1);
   3653       Move(a3, a2, src2);
   3654     }
   3655   }
   3656 }
   3657 
   3658 
   3659 // -----------------------------------------------------------------------------
   3660 // JavaScript invokes.
   3661 
   3662 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
   3663                                     const ParameterCount& actual,
   3664                                     Handle<Code> code_constant,
   3665                                     Register code_reg,
   3666                                     Label* done,
   3667                                     bool* definitely_mismatches,
   3668                                     InvokeFlag flag,
   3669                                     const CallWrapper& call_wrapper) {
   3670   bool definitely_matches = false;
   3671   *definitely_mismatches = false;
   3672   Label regular_invoke;
   3673 
   3674   // Check whether the expected and actual arguments count match. If not,
   3675   // setup registers according to contract with ArgumentsAdaptorTrampoline:
   3676   //  a0: actual arguments count
   3677   //  a1: function (passed through to callee)
   3678   //  a2: expected arguments count
   3679 
   3680   // The code below is made a lot easier because the calling code already sets
   3681   // up actual and expected registers according to the contract if values are
   3682   // passed in registers.
   3683   ASSERT(actual.is_immediate() || actual.reg().is(a0));
   3684   ASSERT(expected.is_immediate() || expected.reg().is(a2));
   3685   ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(a3));
   3686 
   3687   if (expected.is_immediate()) {
   3688     ASSERT(actual.is_immediate());
   3689     if (expected.immediate() == actual.immediate()) {
   3690       definitely_matches = true;
   3691     } else {
   3692       li(a0, Operand(actual.immediate()));
   3693       const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
   3694       if (expected.immediate() == sentinel) {
   3695         // Don't worry about adapting arguments for builtins that
   3696         // don't want that done. Skip adaption code by making it look
   3697         // like we have a match between expected and actual number of
   3698         // arguments.
   3699         definitely_matches = true;
   3700       } else {
   3701         *definitely_mismatches = true;
   3702         li(a2, Operand(expected.immediate()));
   3703       }
   3704     }
   3705   } else if (actual.is_immediate()) {
   3706     Branch(&regular_invoke, eq, expected.reg(), Operand(actual.immediate()));
   3707     li(a0, Operand(actual.immediate()));
   3708   } else {
   3709     Branch(&regular_invoke, eq, expected.reg(), Operand(actual.reg()));
   3710   }
   3711 
   3712   if (!definitely_matches) {
   3713     if (!code_constant.is_null()) {
   3714       li(a3, Operand(code_constant));
   3715       addiu(a3, a3, Code::kHeaderSize - kHeapObjectTag);
   3716     }
   3717 
   3718     Handle<Code> adaptor =
   3719         isolate()->builtins()->ArgumentsAdaptorTrampoline();
   3720     if (flag == CALL_FUNCTION) {
   3721       call_wrapper.BeforeCall(CallSize(adaptor));
   3722       Call(adaptor);
   3723       call_wrapper.AfterCall();
   3724       if (!*definitely_mismatches) {
   3725         Branch(done);
   3726       }
   3727     } else {
   3728       Jump(adaptor, RelocInfo::CODE_TARGET);
   3729     }
   3730     bind(&regular_invoke);
   3731   }
   3732 }
   3733 
   3734 
   3735 void MacroAssembler::InvokeCode(Register code,
   3736                                 const ParameterCount& expected,
   3737                                 const ParameterCount& actual,
   3738                                 InvokeFlag flag,
   3739                                 const CallWrapper& call_wrapper) {
   3740   // You can't call a function without a valid frame.
   3741   ASSERT(flag == JUMP_FUNCTION || has_frame());
   3742 
   3743   Label done;
   3744 
   3745   bool definitely_mismatches = false;
   3746   InvokePrologue(expected, actual, Handle<Code>::null(), code,
   3747                  &done, &definitely_mismatches, flag,
   3748                  call_wrapper);
   3749   if (!definitely_mismatches) {
   3750     if (flag == CALL_FUNCTION) {
   3751       call_wrapper.BeforeCall(CallSize(code));
   3752       Call(code);
   3753       call_wrapper.AfterCall();
   3754     } else {
   3755       ASSERT(flag == JUMP_FUNCTION);
   3756       Jump(code);
   3757     }
   3758     // Continue here if InvokePrologue does handle the invocation due to
   3759     // mismatched parameter counts.
   3760     bind(&done);
   3761   }
   3762 }
   3763 
   3764 
   3765 void MacroAssembler::InvokeFunction(Register function,
   3766                                     const ParameterCount& actual,
   3767                                     InvokeFlag flag,
   3768                                     const CallWrapper& call_wrapper) {
   3769   // You can't call a function without a valid frame.
   3770   ASSERT(flag == JUMP_FUNCTION || has_frame());
   3771 
   3772   // Contract with called JS functions requires that function is passed in a1.
   3773   ASSERT(function.is(a1));
   3774   Register expected_reg = a2;
   3775   Register code_reg = a3;
   3776 
   3777   lw(code_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   3778   lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
   3779   lw(expected_reg,
   3780       FieldMemOperand(code_reg,
   3781                       SharedFunctionInfo::kFormalParameterCountOffset));
   3782   sra(expected_reg, expected_reg, kSmiTagSize);
   3783   lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
   3784 
   3785   ParameterCount expected(expected_reg);
   3786   InvokeCode(code_reg, expected, actual, flag, call_wrapper);
   3787 }
   3788 
   3789 
   3790 void MacroAssembler::InvokeFunction(Register function,
   3791                                     const ParameterCount& expected,
   3792                                     const ParameterCount& actual,
   3793                                     InvokeFlag flag,
   3794                                     const CallWrapper& call_wrapper) {
   3795   // You can't call a function without a valid frame.
   3796   ASSERT(flag == JUMP_FUNCTION || has_frame());
   3797 
   3798   // Contract with called JS functions requires that function is passed in a1.
   3799   ASSERT(function.is(a1));
   3800 
   3801   // Get the function and setup the context.
   3802   lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
   3803 
   3804   // We call indirectly through the code field in the function to
   3805   // allow recompilation to take effect without changing any of the
   3806   // call sites.
   3807   lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
   3808   InvokeCode(a3, expected, actual, flag, call_wrapper);
   3809 }
   3810 
   3811 
   3812 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
   3813                                     const ParameterCount& expected,
   3814                                     const ParameterCount& actual,
   3815                                     InvokeFlag flag,
   3816                                     const CallWrapper& call_wrapper) {
   3817   li(a1, function);
   3818   InvokeFunction(a1, expected, actual, flag, call_wrapper);
   3819 }
   3820 
   3821 
   3822 void MacroAssembler::IsObjectJSObjectType(Register heap_object,
   3823                                           Register map,
   3824                                           Register scratch,
   3825                                           Label* fail) {
   3826   lw(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
   3827   IsInstanceJSObjectType(map, scratch, fail);
   3828 }
   3829 
   3830 
   3831 void MacroAssembler::IsInstanceJSObjectType(Register map,
   3832                                             Register scratch,
   3833                                             Label* fail) {
   3834   lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
   3835   Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
   3836   Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
   3837 }
   3838 
   3839 
   3840 void MacroAssembler::IsObjectJSStringType(Register object,
   3841                                           Register scratch,
   3842                                           Label* fail) {
   3843   ASSERT(kNotStringTag != 0);
   3844 
   3845   lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   3846   lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   3847   And(scratch, scratch, Operand(kIsNotStringMask));
   3848   Branch(fail, ne, scratch, Operand(zero_reg));
   3849 }
   3850 
   3851 
   3852 void MacroAssembler::IsObjectNameType(Register object,
   3853                                       Register scratch,
   3854                                       Label* fail) {
   3855   lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   3856   lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   3857   Branch(fail, hi, scratch, Operand(LAST_NAME_TYPE));
   3858 }
   3859 
   3860 
   3861 // ---------------------------------------------------------------------------
   3862 // Support functions.
   3863 
   3864 
   3865 void MacroAssembler::TryGetFunctionPrototype(Register function,
   3866                                              Register result,
   3867                                              Register scratch,
   3868                                              Label* miss,
   3869                                              bool miss_on_bound_function) {
   3870   // Check that the receiver isn't a smi.
   3871   JumpIfSmi(function, miss);
   3872 
   3873   // Check that the function really is a function.  Load map into result reg.
   3874   GetObjectType(function, result, scratch);
   3875   Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE));
   3876 
   3877   if (miss_on_bound_function) {
   3878     lw(scratch,
   3879        FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
   3880     lw(scratch,
   3881        FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
   3882     And(scratch, scratch,
   3883         Operand(Smi::FromInt(1 << SharedFunctionInfo::kBoundFunction)));
   3884     Branch(miss, ne, scratch, Operand(zero_reg));
   3885   }
   3886 
   3887   // Make sure that the function has an instance prototype.
   3888   Label non_instance;
   3889   lbu(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
   3890   And(scratch, scratch, Operand(1 << Map::kHasNonInstancePrototype));
   3891   Branch(&non_instance, ne, scratch, Operand(zero_reg));
   3892 
   3893   // Get the prototype or initial map from the function.
   3894   lw(result,
   3895      FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   3896 
   3897   // If the prototype or initial map is the hole, don't return it and
   3898   // simply miss the cache instead. This will allow us to allocate a
   3899   // prototype object on-demand in the runtime system.
   3900   LoadRoot(t8, Heap::kTheHoleValueRootIndex);
   3901   Branch(miss, eq, result, Operand(t8));
   3902 
   3903   // If the function does not have an initial map, we're done.
   3904   Label done;
   3905   GetObjectType(result, scratch, scratch);
   3906   Branch(&done, ne, scratch, Operand(MAP_TYPE));
   3907 
   3908   // Get the prototype from the initial map.
   3909   lw(result, FieldMemOperand(result, Map::kPrototypeOffset));
   3910   jmp(&done);
   3911 
   3912   // Non-instance prototype: Fetch prototype from constructor field
   3913   // in initial map.
   3914   bind(&non_instance);
   3915   lw(result, FieldMemOperand(result, Map::kConstructorOffset));
   3916 
   3917   // All done.
   3918   bind(&done);
   3919 }
   3920 
   3921 
   3922 void MacroAssembler::GetObjectType(Register object,
   3923                                    Register map,
   3924                                    Register type_reg) {
   3925   lw(map, FieldMemOperand(object, HeapObject::kMapOffset));
   3926   lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
   3927 }
   3928 
   3929 
   3930 // -----------------------------------------------------------------------------
   3931 // Runtime calls.
   3932 
   3933 void MacroAssembler::CallStub(CodeStub* stub,
   3934                               TypeFeedbackId ast_id,
   3935                               Condition cond,
   3936                               Register r1,
   3937                               const Operand& r2,
   3938                               BranchDelaySlot bd) {
   3939   ASSERT(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
   3940   Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id,
   3941        cond, r1, r2, bd);
   3942 }
   3943 
   3944 
   3945 void MacroAssembler::TailCallStub(CodeStub* stub,
   3946                                   Condition cond,
   3947                                   Register r1,
   3948                                   const Operand& r2,
   3949                                   BranchDelaySlot bd) {
   3950   Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2, bd);
   3951 }
   3952 
   3953 
   3954 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
   3955   return ref0.address() - ref1.address();
   3956 }
   3957 
   3958 
   3959 void MacroAssembler::CallApiFunctionAndReturn(
   3960     Register function_address,
   3961     ExternalReference thunk_ref,
   3962     int stack_space,
   3963     MemOperand return_value_operand,
   3964     MemOperand* context_restore_operand) {
   3965   ExternalReference next_address =
   3966       ExternalReference::handle_scope_next_address(isolate());
   3967   const int kNextOffset = 0;
   3968   const int kLimitOffset = AddressOffset(
   3969       ExternalReference::handle_scope_limit_address(isolate()),
   3970       next_address);
   3971   const int kLevelOffset = AddressOffset(
   3972       ExternalReference::handle_scope_level_address(isolate()),
   3973       next_address);
   3974 
   3975   ASSERT(function_address.is(a1) || function_address.is(a2));
   3976 
   3977   Label profiler_disabled;
   3978   Label end_profiler_check;
   3979   li(t9, Operand(ExternalReference::is_profiling_address(isolate())));
   3980   lb(t9, MemOperand(t9, 0));
   3981   Branch(&profiler_disabled, eq, t9, Operand(zero_reg));
   3982 
   3983   // Additional parameter is the address of the actual callback.
   3984   li(t9, Operand(thunk_ref));
   3985   jmp(&end_profiler_check);
   3986 
   3987   bind(&profiler_disabled);
   3988   mov(t9, function_address);
   3989   bind(&end_profiler_check);
   3990 
   3991   // Allocate HandleScope in callee-save registers.
   3992   li(s3, Operand(next_address));
   3993   lw(s0, MemOperand(s3, kNextOffset));
   3994   lw(s1, MemOperand(s3, kLimitOffset));
   3995   lw(s2, MemOperand(s3, kLevelOffset));
   3996   Addu(s2, s2, Operand(1));
   3997   sw(s2, MemOperand(s3, kLevelOffset));
   3998 
   3999   if (FLAG_log_timer_events) {
   4000     FrameScope frame(this, StackFrame::MANUAL);
   4001     PushSafepointRegisters();
   4002     PrepareCallCFunction(1, a0);
   4003     li(a0, Operand(ExternalReference::isolate_address(isolate())));
   4004     CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
   4005     PopSafepointRegisters();
   4006   }
   4007 
   4008   // Native call returns to the DirectCEntry stub which redirects to the
   4009   // return address pushed on stack (could have moved after GC).
   4010   // DirectCEntry stub itself is generated early and never moves.
   4011   DirectCEntryStub stub(isolate());
   4012   stub.GenerateCall(this, t9);
   4013 
   4014   if (FLAG_log_timer_events) {
   4015     FrameScope frame(this, StackFrame::MANUAL);
   4016     PushSafepointRegisters();
   4017     PrepareCallCFunction(1, a0);
   4018     li(a0, Operand(ExternalReference::isolate_address(isolate())));
   4019     CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1);
   4020     PopSafepointRegisters();
   4021   }
   4022 
   4023   Label promote_scheduled_exception;
   4024   Label exception_handled;
   4025   Label delete_allocated_handles;
   4026   Label leave_exit_frame;
   4027   Label return_value_loaded;
   4028 
   4029   // Load value from ReturnValue.
   4030   lw(v0, return_value_operand);
   4031   bind(&return_value_loaded);
   4032 
   4033   // No more valid handles (the result handle was the last one). Restore
   4034   // previous handle scope.
   4035   sw(s0, MemOperand(s3, kNextOffset));
   4036   if (emit_debug_code()) {
   4037     lw(a1, MemOperand(s3, kLevelOffset));
   4038     Check(eq, kUnexpectedLevelAfterReturnFromApiCall, a1, Operand(s2));
   4039   }
   4040   Subu(s2, s2, Operand(1));
   4041   sw(s2, MemOperand(s3, kLevelOffset));
   4042   lw(at, MemOperand(s3, kLimitOffset));
   4043   Branch(&delete_allocated_handles, ne, s1, Operand(at));
   4044 
   4045   // Check if the function scheduled an exception.
   4046   bind(&leave_exit_frame);
   4047   LoadRoot(t0, Heap::kTheHoleValueRootIndex);
   4048   li(at, Operand(ExternalReference::scheduled_exception_address(isolate())));
   4049   lw(t1, MemOperand(at));
   4050   Branch(&promote_scheduled_exception, ne, t0, Operand(t1));
   4051   bind(&exception_handled);
   4052 
   4053   bool restore_context = context_restore_operand != NULL;
   4054   if (restore_context) {
   4055     lw(cp, *context_restore_operand);
   4056   }
   4057   li(s0, Operand(stack_space));
   4058   LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN);
   4059 
   4060   bind(&promote_scheduled_exception);
   4061   {
   4062     FrameScope frame(this, StackFrame::INTERNAL);
   4063     CallExternalReference(
   4064         ExternalReference(Runtime::kHiddenPromoteScheduledException, isolate()),
   4065         0);
   4066   }
   4067   jmp(&exception_handled);
   4068 
   4069   // HandleScope limit has changed. Delete allocated extensions.
   4070   bind(&delete_allocated_handles);
   4071   sw(s1, MemOperand(s3, kLimitOffset));
   4072   mov(s0, v0);
   4073   mov(a0, v0);
   4074   PrepareCallCFunction(1, s1);
   4075   li(a0, Operand(ExternalReference::isolate_address(isolate())));
   4076   CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate()),
   4077       1);
   4078   mov(v0, s0);
   4079   jmp(&leave_exit_frame);
   4080 }
   4081 
   4082 
   4083 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
   4084   return has_frame_ || !stub->SometimesSetsUpAFrame();
   4085 }
   4086 
   4087 
   4088 void MacroAssembler::IndexFromHash(Register hash, Register index) {
   4089   // If the hash field contains an array index pick it out. The assert checks
   4090   // that the constants for the maximum number of digits for an array index
   4091   // cached in the hash field and the number of bits reserved for it does not
   4092   // conflict.
   4093   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
   4094          (1 << String::kArrayIndexValueBits));
   4095   DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash);
   4096 }
   4097 
   4098 
   4099 void MacroAssembler::ObjectToDoubleFPURegister(Register object,
   4100                                                FPURegister result,
   4101                                                Register scratch1,
   4102                                                Register scratch2,
   4103                                                Register heap_number_map,
   4104                                                Label* not_number,
   4105                                                ObjectToDoubleFlags flags) {
   4106   Label done;
   4107   if ((flags & OBJECT_NOT_SMI) == 0) {
   4108     Label not_smi;
   4109     JumpIfNotSmi(object, &not_smi);
   4110     // Remove smi tag and convert to double.
   4111     sra(scratch1, object, kSmiTagSize);
   4112     mtc1(scratch1, result);
   4113     cvt_d_w(result, result);
   4114     Branch(&done);
   4115     bind(&not_smi);
   4116   }
   4117   // Check for heap number and load double value from it.
   4118   lw(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
   4119   Branch(not_number, ne, scratch1, Operand(heap_number_map));
   4120 
   4121   if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
   4122     // If exponent is all ones the number is either a NaN or +/-Infinity.
   4123     Register exponent = scratch1;
   4124     Register mask_reg = scratch2;
   4125     lw(exponent, FieldMemOperand(object, HeapNumber::kExponentOffset));
   4126     li(mask_reg, HeapNumber::kExponentMask);
   4127 
   4128     And(exponent, exponent, mask_reg);
   4129     Branch(not_number, eq, exponent, Operand(mask_reg));
   4130   }
   4131   ldc1(result, FieldMemOperand(object, HeapNumber::kValueOffset));
   4132   bind(&done);
   4133 }
   4134 
   4135 
   4136 void MacroAssembler::SmiToDoubleFPURegister(Register smi,
   4137                                             FPURegister value,
   4138                                             Register scratch1) {
   4139   sra(scratch1, smi, kSmiTagSize);
   4140   mtc1(scratch1, value);
   4141   cvt_d_w(value, value);
   4142 }
   4143 
   4144 
   4145 void MacroAssembler::AdduAndCheckForOverflow(Register dst,
   4146                                              Register left,
   4147                                              Register right,
   4148                                              Register overflow_dst,
   4149                                              Register scratch) {
   4150   ASSERT(!dst.is(overflow_dst));
   4151   ASSERT(!dst.is(scratch));
   4152   ASSERT(!overflow_dst.is(scratch));
   4153   ASSERT(!overflow_dst.is(left));
   4154   ASSERT(!overflow_dst.is(right));
   4155 
   4156   if (left.is(right) && dst.is(left)) {
   4157     ASSERT(!dst.is(t9));
   4158     ASSERT(!scratch.is(t9));
   4159     ASSERT(!left.is(t9));
   4160     ASSERT(!right.is(t9));
   4161     ASSERT(!overflow_dst.is(t9));
   4162     mov(t9, right);
   4163     right = t9;
   4164   }
   4165 
   4166   if (dst.is(left)) {
   4167     mov(scratch, left);  // Preserve left.
   4168     addu(dst, left, right);  // Left is overwritten.
   4169     xor_(scratch, dst, scratch);  // Original left.
   4170     xor_(overflow_dst, dst, right);
   4171     and_(overflow_dst, overflow_dst, scratch);
   4172   } else if (dst.is(right)) {
   4173     mov(scratch, right);  // Preserve right.
   4174     addu(dst, left, right);  // Right is overwritten.
   4175     xor_(scratch, dst, scratch);  // Original right.
   4176     xor_(overflow_dst, dst, left);
   4177     and_(overflow_dst, overflow_dst, scratch);
   4178   } else {
   4179     addu(dst, left, right);
   4180     xor_(overflow_dst, dst, left);
   4181     xor_(scratch, dst, right);
   4182     and_(overflow_dst, scratch, overflow_dst);
   4183   }
   4184 }
   4185 
   4186 
   4187 void MacroAssembler::SubuAndCheckForOverflow(Register dst,
   4188                                              Register left,
   4189                                              Register right,
   4190                                              Register overflow_dst,
   4191                                              Register scratch) {
   4192   ASSERT(!dst.is(overflow_dst));
   4193   ASSERT(!dst.is(scratch));
   4194   ASSERT(!overflow_dst.is(scratch));
   4195   ASSERT(!overflow_dst.is(left));
   4196   ASSERT(!overflow_dst.is(right));
   4197   ASSERT(!scratch.is(left));
   4198   ASSERT(!scratch.is(right));
   4199 
   4200   // This happens with some crankshaft code. Since Subu works fine if
   4201   // left == right, let's not make that restriction here.
   4202   if (left.is(right)) {
   4203     mov(dst, zero_reg);
   4204     mov(overflow_dst, zero_reg);
   4205     return;
   4206   }
   4207 
   4208   if (dst.is(left)) {
   4209     mov(scratch, left);  // Preserve left.
   4210     subu(dst, left, right);  // Left is overwritten.
   4211     xor_(overflow_dst, dst, scratch);  // scratch is original left.
   4212     xor_(scratch, scratch, right);  // scratch is original left.
   4213     and_(overflow_dst, scratch, overflow_dst);
   4214   } else if (dst.is(right)) {
   4215     mov(scratch, right);  // Preserve right.
   4216     subu(dst, left, right);  // Right is overwritten.
   4217     xor_(overflow_dst, dst, left);
   4218     xor_(scratch, left, scratch);  // Original right.
   4219     and_(overflow_dst, scratch, overflow_dst);
   4220   } else {
   4221     subu(dst, left, right);
   4222     xor_(overflow_dst, dst, left);
   4223     xor_(scratch, left, right);
   4224     and_(overflow_dst, scratch, overflow_dst);
   4225   }
   4226 }
   4227 
   4228 
   4229 void MacroAssembler::CallRuntime(const Runtime::Function* f,
   4230                                  int num_arguments,
   4231                                  SaveFPRegsMode save_doubles) {
   4232   // All parameters are on the stack. v0 has the return value after call.
   4233 
   4234   // If the expected number of arguments of the runtime function is
   4235   // constant, we check that the actual number of arguments match the
   4236   // expectation.
   4237   CHECK(f->nargs < 0 || f->nargs == num_arguments);
   4238 
   4239   // TODO(1236192): Most runtime routines don't need the number of
   4240   // arguments passed in because it is constant. At some point we
   4241   // should remove this need and make the runtime routine entry code
   4242   // smarter.
   4243   PrepareCEntryArgs(num_arguments);
   4244   PrepareCEntryFunction(ExternalReference(f, isolate()));
   4245   CEntryStub stub(isolate(), 1, save_doubles);
   4246   CallStub(&stub);
   4247 }
   4248 
   4249 
   4250 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
   4251                                            int num_arguments,
   4252                                            BranchDelaySlot bd) {
   4253   PrepareCEntryArgs(num_arguments);
   4254   PrepareCEntryFunction(ext);
   4255 
   4256   CEntryStub stub(isolate(), 1);
   4257   CallStub(&stub, TypeFeedbackId::None(), al, zero_reg, Operand(zero_reg), bd);
   4258 }
   4259 
   4260 
   4261 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
   4262                                                int num_arguments,
   4263                                                int result_size) {
   4264   // TODO(1236192): Most runtime routines don't need the number of
   4265   // arguments passed in because it is constant. At some point we
   4266   // should remove this need and make the runtime routine entry code
   4267   // smarter.
   4268   PrepareCEntryArgs(num_arguments);
   4269   JumpToExternalReference(ext);
   4270 }
   4271 
   4272 
   4273 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
   4274                                      int num_arguments,
   4275                                      int result_size) {
   4276   TailCallExternalReference(ExternalReference(fid, isolate()),
   4277                             num_arguments,
   4278                             result_size);
   4279 }
   4280 
   4281 
   4282 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
   4283                                              BranchDelaySlot bd) {
   4284   PrepareCEntryFunction(builtin);
   4285   CEntryStub stub(isolate(), 1);
   4286   Jump(stub.GetCode(),
   4287        RelocInfo::CODE_TARGET,
   4288        al,
   4289        zero_reg,
   4290        Operand(zero_reg),
   4291        bd);
   4292 }
   4293 
   4294 
   4295 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
   4296                                    InvokeFlag flag,
   4297                                    const CallWrapper& call_wrapper) {
   4298   // You can't call a builtin without a valid frame.
   4299   ASSERT(flag == JUMP_FUNCTION || has_frame());
   4300 
   4301   GetBuiltinEntry(t9, id);
   4302   if (flag == CALL_FUNCTION) {
   4303     call_wrapper.BeforeCall(CallSize(t9));
   4304     Call(t9);
   4305     call_wrapper.AfterCall();
   4306   } else {
   4307     ASSERT(flag == JUMP_FUNCTION);
   4308     Jump(t9);
   4309   }
   4310 }
   4311 
   4312 
   4313 void MacroAssembler::GetBuiltinFunction(Register target,
   4314                                         Builtins::JavaScript id) {
   4315   // Load the builtins object into target register.
   4316   lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
   4317   lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
   4318   // Load the JavaScript builtin function from the builtins object.
   4319   lw(target, FieldMemOperand(target,
   4320                           JSBuiltinsObject::OffsetOfFunctionWithId(id)));
   4321 }
   4322 
   4323 
   4324 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
   4325   ASSERT(!target.is(a1));
   4326   GetBuiltinFunction(a1, id);
   4327   // Load the code entry point from the builtins object.
   4328   lw(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
   4329 }
   4330 
   4331 
   4332 void MacroAssembler::SetCounter(StatsCounter* counter, int value,
   4333                                 Register scratch1, Register scratch2) {
   4334   if (FLAG_native_code_counters && counter->Enabled()) {
   4335     li(scratch1, Operand(value));
   4336     li(scratch2, Operand(ExternalReference(counter)));
   4337     sw(scratch1, MemOperand(scratch2));
   4338   }
   4339 }
   4340 
   4341 
   4342 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
   4343                                       Register scratch1, Register scratch2) {
   4344   ASSERT(value > 0);
   4345   if (FLAG_native_code_counters && counter->Enabled()) {
   4346     li(scratch2, Operand(ExternalReference(counter)));
   4347     lw(scratch1, MemOperand(scratch2));
   4348     Addu(scratch1, scratch1, Operand(value));
   4349     sw(scratch1, MemOperand(scratch2));
   4350   }
   4351 }
   4352 
   4353 
   4354 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
   4355                                       Register scratch1, Register scratch2) {
   4356   ASSERT(value > 0);
   4357   if (FLAG_native_code_counters && counter->Enabled()) {
   4358     li(scratch2, Operand(ExternalReference(counter)));
   4359     lw(scratch1, MemOperand(scratch2));
   4360     Subu(scratch1, scratch1, Operand(value));
   4361     sw(scratch1, MemOperand(scratch2));
   4362   }
   4363 }
   4364 
   4365 
   4366 // -----------------------------------------------------------------------------
   4367 // Debugging.
   4368 
   4369 void MacroAssembler::Assert(Condition cc, BailoutReason reason,
   4370                             Register rs, Operand rt) {
   4371   if (emit_debug_code())
   4372     Check(cc, reason, rs, rt);
   4373 }
   4374 
   4375 
   4376 void MacroAssembler::AssertFastElements(Register elements) {
   4377   if (emit_debug_code()) {
   4378     ASSERT(!elements.is(at));
   4379     Label ok;
   4380     push(elements);
   4381     lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
   4382     LoadRoot(at, Heap::kFixedArrayMapRootIndex);
   4383     Branch(&ok, eq, elements, Operand(at));
   4384     LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex);
   4385     Branch(&ok, eq, elements, Operand(at));
   4386     LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
   4387     Branch(&ok, eq, elements, Operand(at));
   4388     Abort(kJSObjectWithFastElementsMapHasSlowElements);
   4389     bind(&ok);
   4390     pop(elements);
   4391   }
   4392 }
   4393 
   4394 
   4395 void MacroAssembler::Check(Condition cc, BailoutReason reason,
   4396                            Register rs, Operand rt) {
   4397   Label L;
   4398   Branch(&L, cc, rs, rt);
   4399   Abort(reason);
   4400   // Will not return here.
   4401   bind(&L);
   4402 }
   4403 
   4404 
   4405 void MacroAssembler::Abort(BailoutReason reason) {
   4406   Label abort_start;
   4407   bind(&abort_start);
   4408 #ifdef DEBUG
   4409   const char* msg = GetBailoutReason(reason);
   4410   if (msg != NULL) {
   4411     RecordComment("Abort message: ");
   4412     RecordComment(msg);
   4413   }
   4414 
   4415   if (FLAG_trap_on_abort) {
   4416     stop(msg);
   4417     return;
   4418   }
   4419 #endif
   4420 
   4421   li(a0, Operand(Smi::FromInt(reason)));
   4422   push(a0);
   4423   // Disable stub call restrictions to always allow calls to abort.
   4424   if (!has_frame_) {
   4425     // We don't actually want to generate a pile of code for this, so just
   4426     // claim there is a stack frame, without generating one.
   4427     FrameScope scope(this, StackFrame::NONE);
   4428     CallRuntime(Runtime::kAbort, 1);
   4429   } else {
   4430     CallRuntime(Runtime::kAbort, 1);
   4431   }
   4432   // Will not return here.
   4433   if (is_trampoline_pool_blocked()) {
   4434     // If the calling code cares about the exact number of
   4435     // instructions generated, we insert padding here to keep the size
   4436     // of the Abort macro constant.
   4437     // Currently in debug mode with debug_code enabled the number of
   4438     // generated instructions is 10, so we use this as a maximum value.
   4439     static const int kExpectedAbortInstructions = 10;
   4440     int abort_instructions = InstructionsGeneratedSince(&abort_start);
   4441     ASSERT(abort_instructions <= kExpectedAbortInstructions);
   4442     while (abort_instructions++ < kExpectedAbortInstructions) {
   4443       nop();
   4444     }
   4445   }
   4446 }
   4447 
   4448 
   4449 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
   4450   if (context_chain_length > 0) {
   4451     // Move up the chain of contexts to the context containing the slot.
   4452     lw(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   4453     for (int i = 1; i < context_chain_length; i++) {
   4454       lw(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   4455     }
   4456   } else {
   4457     // Slot is in the current function context.  Move it into the
   4458     // destination register in case we store into it (the write barrier
   4459     // cannot be allowed to destroy the context in esi).
   4460     Move(dst, cp);
   4461   }
   4462 }
   4463 
   4464 
   4465 void MacroAssembler::LoadTransitionedArrayMapConditional(
   4466     ElementsKind expected_kind,
   4467     ElementsKind transitioned_kind,
   4468     Register map_in_out,
   4469     Register scratch,
   4470     Label* no_map_match) {
   4471   // Load the global or builtins object from the current context.
   4472   lw(scratch,
   4473      MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
   4474   lw(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
   4475 
   4476   // Check that the function's map is the same as the expected cached map.
   4477   lw(scratch,
   4478      MemOperand(scratch,
   4479                 Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX)));
   4480   size_t offset = expected_kind * kPointerSize +
   4481       FixedArrayBase::kHeaderSize;
   4482   lw(at, FieldMemOperand(scratch, offset));
   4483   Branch(no_map_match, ne, map_in_out, Operand(at));
   4484 
   4485   // Use the transitioned cached map.
   4486   offset = transitioned_kind * kPointerSize +
   4487       FixedArrayBase::kHeaderSize;
   4488   lw(map_in_out, FieldMemOperand(scratch, offset));
   4489 }
   4490 
   4491 
   4492 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
   4493   // Load the global or builtins object from the current context.
   4494   lw(function,
   4495      MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
   4496   // Load the native context from the global or builtins object.
   4497   lw(function, FieldMemOperand(function,
   4498                                GlobalObject::kNativeContextOffset));
   4499   // Load the function from the native context.
   4500   lw(function, MemOperand(function, Context::SlotOffset(index)));
   4501 }
   4502 
   4503 
   4504 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
   4505                                                   Register map,
   4506                                                   Register scratch) {
   4507   // Load the initial map. The global functions all have initial maps.
   4508   lw(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   4509   if (emit_debug_code()) {
   4510     Label ok, fail;
   4511     CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
   4512     Branch(&ok);
   4513     bind(&fail);
   4514     Abort(kGlobalFunctionsMustHaveInitialMap);
   4515     bind(&ok);
   4516   }
   4517 }
   4518 
   4519 
   4520 void MacroAssembler::StubPrologue() {
   4521     Push(ra, fp, cp);
   4522     Push(Smi::FromInt(StackFrame::STUB));
   4523     // Adjust FP to point to saved FP.
   4524     Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
   4525 }
   4526 
   4527 
   4528 void MacroAssembler::Prologue(bool code_pre_aging) {
   4529   PredictableCodeSizeScope predictible_code_size_scope(
   4530       this, kNoCodeAgeSequenceLength);
   4531   // The following three instructions must remain together and unmodified
   4532   // for code aging to work properly.
   4533   if (code_pre_aging) {
   4534     // Pre-age the code.
   4535     Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
   4536     nop(Assembler::CODE_AGE_MARKER_NOP);
   4537     // Load the stub address to t9 and call it,
   4538     // GetCodeAgeAndParity() extracts the stub address from this instruction.
   4539     li(t9,
   4540        Operand(reinterpret_cast<uint32_t>(stub->instruction_start())),
   4541        CONSTANT_SIZE);
   4542     nop();  // Prevent jalr to jal optimization.
   4543     jalr(t9, a0);
   4544     nop();  // Branch delay slot nop.
   4545     nop();  // Pad the empty space.
   4546   } else {
   4547     Push(ra, fp, cp, a1);
   4548     nop(Assembler::CODE_AGE_SEQUENCE_NOP);
   4549     // Adjust fp to point to caller's fp.
   4550     Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
   4551   }
   4552 }
   4553 
   4554 
   4555 void MacroAssembler::EnterFrame(StackFrame::Type type) {
   4556   addiu(sp, sp, -5 * kPointerSize);
   4557   li(t8, Operand(Smi::FromInt(type)));
   4558   li(t9, Operand(CodeObject()), CONSTANT_SIZE);
   4559   sw(ra, MemOperand(sp, 4 * kPointerSize));
   4560   sw(fp, MemOperand(sp, 3 * kPointerSize));
   4561   sw(cp, MemOperand(sp, 2 * kPointerSize));
   4562   sw(t8, MemOperand(sp, 1 * kPointerSize));
   4563   sw(t9, MemOperand(sp, 0 * kPointerSize));
   4564   // Adjust FP to point to saved FP.
   4565   Addu(fp, sp,
   4566        Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
   4567 }
   4568 
   4569 
   4570 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
   4571   mov(sp, fp);
   4572   lw(fp, MemOperand(sp, 0 * kPointerSize));
   4573   lw(ra, MemOperand(sp, 1 * kPointerSize));
   4574   addiu(sp, sp, 2 * kPointerSize);
   4575 }
   4576 
   4577 
   4578 void MacroAssembler::EnterExitFrame(bool save_doubles,
   4579                                     int stack_space) {
   4580   // Set up the frame structure on the stack.
   4581   STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement);
   4582   STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset);
   4583   STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset);
   4584 
   4585   // This is how the stack will look:
   4586   // fp + 2 (==kCallerSPDisplacement) - old stack's end
   4587   // [fp + 1 (==kCallerPCOffset)] - saved old ra
   4588   // [fp + 0 (==kCallerFPOffset)] - saved old fp
   4589   // [fp - 1 (==kSPOffset)] - sp of the called function
   4590   // [fp - 2 (==kCodeOffset)] - CodeObject
   4591   // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the
   4592   //   new stack (will contain saved ra)
   4593 
   4594   // Save registers.
   4595   addiu(sp, sp, -4 * kPointerSize);
   4596   sw(ra, MemOperand(sp, 3 * kPointerSize));
   4597   sw(fp, MemOperand(sp, 2 * kPointerSize));
   4598   addiu(fp, sp, 2 * kPointerSize);  // Set up new frame pointer.
   4599 
   4600   if (emit_debug_code()) {
   4601     sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset));
   4602   }
   4603 
   4604   // Accessed from ExitFrame::code_slot.
   4605   li(t8, Operand(CodeObject()), CONSTANT_SIZE);
   4606   sw(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
   4607 
   4608   // Save the frame pointer and the context in top.
   4609   li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
   4610   sw(fp, MemOperand(t8));
   4611   li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   4612   sw(cp, MemOperand(t8));
   4613 
   4614   const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
   4615   if (save_doubles) {
   4616     // The stack  must be allign to 0 modulo 8 for stores with sdc1.
   4617     ASSERT(kDoubleSize == frame_alignment);
   4618     if (frame_alignment > 0) {
   4619       ASSERT(IsPowerOf2(frame_alignment));
   4620       And(sp, sp, Operand(-frame_alignment));  // Align stack.
   4621     }
   4622     int space = FPURegister::kMaxNumRegisters * kDoubleSize;
   4623     Subu(sp, sp, Operand(space));
   4624     // Remember: we only need to save every 2nd double FPU value.
   4625     for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
   4626       FPURegister reg = FPURegister::from_code(i);
   4627       sdc1(reg, MemOperand(sp, i * kDoubleSize));
   4628     }
   4629   }
   4630 
   4631   // Reserve place for the return address, stack space and an optional slot
   4632   // (used by the DirectCEntryStub to hold the return value if a struct is
   4633   // returned) and align the frame preparing for calling the runtime function.
   4634   ASSERT(stack_space >= 0);
   4635   Subu(sp, sp, Operand((stack_space + 2) * kPointerSize));
   4636   if (frame_alignment > 0) {
   4637     ASSERT(IsPowerOf2(frame_alignment));
   4638     And(sp, sp, Operand(-frame_alignment));  // Align stack.
   4639   }
   4640 
   4641   // Set the exit frame sp value to point just before the return address
   4642   // location.
   4643   addiu(at, sp, kPointerSize);
   4644   sw(at, MemOperand(fp, ExitFrameConstants::kSPOffset));
   4645 }
   4646 
   4647 
   4648 void MacroAssembler::LeaveExitFrame(bool save_doubles,
   4649                                     Register argument_count,
   4650                                     bool restore_context,
   4651                                     bool do_return) {
   4652   // Optionally restore all double registers.
   4653   if (save_doubles) {
   4654     // Remember: we only need to restore every 2nd double FPU value.
   4655     lw(t8, MemOperand(fp, ExitFrameConstants::kSPOffset));
   4656     for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
   4657       FPURegister reg = FPURegister::from_code(i);
   4658       ldc1(reg, MemOperand(t8, i  * kDoubleSize + kPointerSize));
   4659     }
   4660   }
   4661 
   4662   // Clear top frame.
   4663   li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
   4664   sw(zero_reg, MemOperand(t8));
   4665 
   4666   // Restore current context from top and clear it in debug mode.
   4667   if (restore_context) {
   4668     li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   4669     lw(cp, MemOperand(t8));
   4670   }
   4671 #ifdef DEBUG
   4672   li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   4673   sw(a3, MemOperand(t8));
   4674 #endif
   4675 
   4676   // Pop the arguments, restore registers, and return.
   4677   mov(sp, fp);  // Respect ABI stack constraint.
   4678   lw(fp, MemOperand(sp, ExitFrameConstants::kCallerFPOffset));
   4679   lw(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset));
   4680 
   4681   if (argument_count.is_valid()) {
   4682     sll(t8, argument_count, kPointerSizeLog2);
   4683     addu(sp, sp, t8);
   4684   }
   4685 
   4686   if (do_return) {
   4687     Ret(USE_DELAY_SLOT);
   4688     // If returning, the instruction in the delay slot will be the addiu below.
   4689   }
   4690   addiu(sp, sp, 8);
   4691 }
   4692 
   4693 
   4694 void MacroAssembler::InitializeNewString(Register string,
   4695                                          Register length,
   4696                                          Heap::RootListIndex map_index,
   4697                                          Register scratch1,
   4698                                          Register scratch2) {
   4699   sll(scratch1, length, kSmiTagSize);
   4700   LoadRoot(scratch2, map_index);
   4701   sw(scratch1, FieldMemOperand(string, String::kLengthOffset));
   4702   li(scratch1, Operand(String::kEmptyHashField));
   4703   sw(scratch2, FieldMemOperand(string, HeapObject::kMapOffset));
   4704   sw(scratch1, FieldMemOperand(string, String::kHashFieldOffset));
   4705 }
   4706 
   4707 
   4708 int MacroAssembler::ActivationFrameAlignment() {
   4709 #if V8_HOST_ARCH_MIPS
   4710   // Running on the real platform. Use the alignment as mandated by the local
   4711   // environment.
   4712   // Note: This will break if we ever start generating snapshots on one Mips
   4713   // platform for another Mips platform with a different alignment.
   4714   return OS::ActivationFrameAlignment();
   4715 #else  // V8_HOST_ARCH_MIPS
   4716   // If we are using the simulator then we should always align to the expected
   4717   // alignment. As the simulator is used to generate snapshots we do not know
   4718   // if the target platform will need alignment, so this is controlled from a
   4719   // flag.
   4720   return FLAG_sim_stack_alignment;
   4721 #endif  // V8_HOST_ARCH_MIPS
   4722 }
   4723 
   4724 
   4725 void MacroAssembler::AssertStackIsAligned() {
   4726   if (emit_debug_code()) {
   4727       const int frame_alignment = ActivationFrameAlignment();
   4728       const int frame_alignment_mask = frame_alignment - 1;
   4729 
   4730       if (frame_alignment > kPointerSize) {
   4731         Label alignment_as_expected;
   4732         ASSERT(IsPowerOf2(frame_alignment));
   4733         andi(at, sp, frame_alignment_mask);
   4734         Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
   4735         // Don't use Check here, as it will call Runtime_Abort re-entering here.
   4736         stop("Unexpected stack alignment");
   4737         bind(&alignment_as_expected);
   4738       }
   4739     }
   4740 }
   4741 
   4742 
   4743 void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
   4744     Register reg,
   4745     Register scratch,
   4746     Label* not_power_of_two_or_zero) {
   4747   Subu(scratch, reg, Operand(1));
   4748   Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt,
   4749          scratch, Operand(zero_reg));
   4750   and_(at, scratch, reg);  // In the delay slot.
   4751   Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg));
   4752 }
   4753 
   4754 
   4755 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
   4756   ASSERT(!reg.is(overflow));
   4757   mov(overflow, reg);  // Save original value.
   4758   SmiTag(reg);
   4759   xor_(overflow, overflow, reg);  // Overflow if (value ^ 2 * value) < 0.
   4760 }
   4761 
   4762 
   4763 void MacroAssembler::SmiTagCheckOverflow(Register dst,
   4764                                          Register src,
   4765                                          Register overflow) {
   4766   if (dst.is(src)) {
   4767     // Fall back to slower case.
   4768     SmiTagCheckOverflow(dst, overflow);
   4769   } else {
   4770     ASSERT(!dst.is(src));
   4771     ASSERT(!dst.is(overflow));
   4772     ASSERT(!src.is(overflow));
   4773     SmiTag(dst, src);
   4774     xor_(overflow, dst, src);  // Overflow if (value ^ 2 * value) < 0.
   4775   }
   4776 }
   4777 
   4778 
   4779 void MacroAssembler::UntagAndJumpIfSmi(Register dst,
   4780                                        Register src,
   4781                                        Label* smi_case) {
   4782   JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT);
   4783   SmiUntag(dst, src);
   4784 }
   4785 
   4786 
   4787 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst,
   4788                                           Register src,
   4789                                           Label* non_smi_case) {
   4790   JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT);
   4791   SmiUntag(dst, src);
   4792 }
   4793 
   4794 void MacroAssembler::JumpIfSmi(Register value,
   4795                                Label* smi_label,
   4796                                Register scratch,
   4797                                BranchDelaySlot bd) {
   4798   ASSERT_EQ(0, kSmiTag);
   4799   andi(scratch, value, kSmiTagMask);
   4800   Branch(bd, smi_label, eq, scratch, Operand(zero_reg));
   4801 }
   4802 
   4803 void MacroAssembler::JumpIfNotSmi(Register value,
   4804                                   Label* not_smi_label,
   4805                                   Register scratch,
   4806                                   BranchDelaySlot bd) {
   4807   ASSERT_EQ(0, kSmiTag);
   4808   andi(scratch, value, kSmiTagMask);
   4809   Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg));
   4810 }
   4811 
   4812 
   4813 void MacroAssembler::JumpIfNotBothSmi(Register reg1,
   4814                                       Register reg2,
   4815                                       Label* on_not_both_smi) {
   4816   STATIC_ASSERT(kSmiTag == 0);
   4817   ASSERT_EQ(1, kSmiTagMask);
   4818   or_(at, reg1, reg2);
   4819   JumpIfNotSmi(at, on_not_both_smi);
   4820 }
   4821 
   4822 
   4823 void MacroAssembler::JumpIfEitherSmi(Register reg1,
   4824                                      Register reg2,
   4825                                      Label* on_either_smi) {
   4826   STATIC_ASSERT(kSmiTag == 0);
   4827   ASSERT_EQ(1, kSmiTagMask);
   4828   // Both Smi tags must be 1 (not Smi).
   4829   and_(at, reg1, reg2);
   4830   JumpIfSmi(at, on_either_smi);
   4831 }
   4832 
   4833 
   4834 void MacroAssembler::AssertNotSmi(Register object) {
   4835   if (emit_debug_code()) {
   4836     STATIC_ASSERT(kSmiTag == 0);
   4837     andi(at, object, kSmiTagMask);
   4838     Check(ne, kOperandIsASmi, at, Operand(zero_reg));
   4839   }
   4840 }
   4841 
   4842 
   4843 void MacroAssembler::AssertSmi(Register object) {
   4844   if (emit_debug_code()) {
   4845     STATIC_ASSERT(kSmiTag == 0);
   4846     andi(at, object, kSmiTagMask);
   4847     Check(eq, kOperandIsASmi, at, Operand(zero_reg));
   4848   }
   4849 }
   4850 
   4851 
   4852 void MacroAssembler::AssertString(Register object) {
   4853   if (emit_debug_code()) {
   4854     STATIC_ASSERT(kSmiTag == 0);
   4855     SmiTst(object, t0);
   4856     Check(ne, kOperandIsASmiAndNotAString, t0, Operand(zero_reg));
   4857     push(object);
   4858     lw(object, FieldMemOperand(object, HeapObject::kMapOffset));
   4859     lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
   4860     Check(lo, kOperandIsNotAString, object, Operand(FIRST_NONSTRING_TYPE));
   4861     pop(object);
   4862   }
   4863 }
   4864 
   4865 
   4866 void MacroAssembler::AssertName(Register object) {
   4867   if (emit_debug_code()) {
   4868     STATIC_ASSERT(kSmiTag == 0);
   4869     SmiTst(object, t0);
   4870     Check(ne, kOperandIsASmiAndNotAName, t0, Operand(zero_reg));
   4871     push(object);
   4872     lw(object, FieldMemOperand(object, HeapObject::kMapOffset));
   4873     lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
   4874     Check(le, kOperandIsNotAName, object, Operand(LAST_NAME_TYPE));
   4875     pop(object);
   4876   }
   4877 }
   4878 
   4879 
   4880 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
   4881                                                      Register scratch) {
   4882   if (emit_debug_code()) {
   4883     Label done_checking;
   4884     AssertNotSmi(object);
   4885     LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
   4886     Branch(&done_checking, eq, object, Operand(scratch));
   4887     push(object);
   4888     lw(object, FieldMemOperand(object, HeapObject::kMapOffset));
   4889     LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex);
   4890     Assert(eq, kExpectedUndefinedOrCell, object, Operand(scratch));
   4891     pop(object);
   4892     bind(&done_checking);
   4893   }
   4894 }
   4895 
   4896 
   4897 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
   4898   if (emit_debug_code()) {
   4899     ASSERT(!reg.is(at));
   4900     LoadRoot(at, index);
   4901     Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at));
   4902   }
   4903 }
   4904 
   4905 
   4906 void MacroAssembler::JumpIfNotHeapNumber(Register object,
   4907                                          Register heap_number_map,
   4908                                          Register scratch,
   4909                                          Label* on_not_heap_number) {
   4910   lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   4911   AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
   4912   Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map));
   4913 }
   4914 
   4915 
   4916 void MacroAssembler::LookupNumberStringCache(Register object,
   4917                                              Register result,
   4918                                              Register scratch1,
   4919                                              Register scratch2,
   4920                                              Register scratch3,
   4921                                              Label* not_found) {
   4922   // Use of registers. Register result is used as a temporary.
   4923   Register number_string_cache = result;
   4924   Register mask = scratch3;
   4925 
   4926   // Load the number string cache.
   4927   LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
   4928 
   4929   // Make the hash mask from the length of the number string cache. It
   4930   // contains two elements (number and string) for each cache entry.
   4931   lw(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset));
   4932   // Divide length by two (length is a smi).
   4933   sra(mask, mask, kSmiTagSize + 1);
   4934   Addu(mask, mask, -1);  // Make mask.
   4935 
   4936   // Calculate the entry in the number string cache. The hash value in the
   4937   // number string cache for smis is just the smi value, and the hash for
   4938   // doubles is the xor of the upper and lower words. See
   4939   // Heap::GetNumberStringCache.
   4940   Label is_smi;
   4941   Label load_result_from_cache;
   4942   JumpIfSmi(object, &is_smi);
   4943   CheckMap(object,
   4944            scratch1,
   4945            Heap::kHeapNumberMapRootIndex,
   4946            not_found,
   4947            DONT_DO_SMI_CHECK);
   4948 
   4949   STATIC_ASSERT(8 == kDoubleSize);
   4950   Addu(scratch1,
   4951        object,
   4952        Operand(HeapNumber::kValueOffset - kHeapObjectTag));
   4953   lw(scratch2, MemOperand(scratch1, kPointerSize));
   4954   lw(scratch1, MemOperand(scratch1, 0));
   4955   Xor(scratch1, scratch1, Operand(scratch2));
   4956   And(scratch1, scratch1, Operand(mask));
   4957 
   4958   // Calculate address of entry in string cache: each entry consists
   4959   // of two pointer sized fields.
   4960   sll(scratch1, scratch1, kPointerSizeLog2 + 1);
   4961   Addu(scratch1, number_string_cache, scratch1);
   4962 
   4963   Register probe = mask;
   4964   lw(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize));
   4965   JumpIfSmi(probe, not_found);
   4966   ldc1(f12, FieldMemOperand(object, HeapNumber::kValueOffset));
   4967   ldc1(f14, FieldMemOperand(probe, HeapNumber::kValueOffset));
   4968   BranchF(&load_result_from_cache, NULL, eq, f12, f14);
   4969   Branch(not_found);
   4970 
   4971   bind(&is_smi);
   4972   Register scratch = scratch1;
   4973   sra(scratch, object, 1);   // Shift away the tag.
   4974   And(scratch, mask, Operand(scratch));
   4975 
   4976   // Calculate address of entry in string cache: each entry consists
   4977   // of two pointer sized fields.
   4978   sll(scratch, scratch, kPointerSizeLog2 + 1);
   4979   Addu(scratch, number_string_cache, scratch);
   4980 
   4981   // Check if the entry is the smi we are looking for.
   4982   lw(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize));
   4983   Branch(not_found, ne, object, Operand(probe));
   4984 
   4985   // Get the result from the cache.
   4986   bind(&load_result_from_cache);
   4987   lw(result, FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
   4988 
   4989   IncrementCounter(isolate()->counters()->number_to_string_native(),
   4990                    1,
   4991                    scratch1,
   4992                    scratch2);
   4993 }
   4994 
   4995 
   4996 void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
   4997     Register first,
   4998     Register second,
   4999     Register scratch1,
   5000     Register scratch2,
   5001     Label* failure) {
   5002   // Test that both first and second are sequential ASCII strings.
   5003   // Assume that they are non-smis.
   5004   lw(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
   5005   lw(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
   5006   lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
   5007   lbu(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
   5008 
   5009   JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1,
   5010                                                scratch2,
   5011                                                scratch1,
   5012                                                scratch2,
   5013                                                failure);
   5014 }
   5015 
   5016 
   5017 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first,
   5018                                                          Register second,
   5019                                                          Register scratch1,
   5020                                                          Register scratch2,
   5021                                                          Label* failure) {
   5022   // Check that neither is a smi.
   5023   STATIC_ASSERT(kSmiTag == 0);
   5024   And(scratch1, first, Operand(second));
   5025   JumpIfSmi(scratch1, failure);
   5026   JumpIfNonSmisNotBothSequentialAsciiStrings(first,
   5027                                              second,
   5028                                              scratch1,
   5029                                              scratch2,
   5030                                              failure);
   5031 }
   5032 
   5033 
   5034 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
   5035     Register first,
   5036     Register second,
   5037     Register scratch1,
   5038     Register scratch2,
   5039     Label* failure) {
   5040   const int kFlatAsciiStringMask =
   5041       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
   5042   const int kFlatAsciiStringTag =
   5043       kStringTag | kOneByteStringTag | kSeqStringTag;
   5044   ASSERT(kFlatAsciiStringTag <= 0xffff);  // Ensure this fits 16-bit immed.
   5045   andi(scratch1, first, kFlatAsciiStringMask);
   5046   Branch(failure, ne, scratch1, Operand(kFlatAsciiStringTag));
   5047   andi(scratch2, second, kFlatAsciiStringMask);
   5048   Branch(failure, ne, scratch2, Operand(kFlatAsciiStringTag));
   5049 }
   5050 
   5051 
   5052 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type,
   5053                                                             Register scratch,
   5054                                                             Label* failure) {
   5055   const int kFlatAsciiStringMask =
   5056       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
   5057   const int kFlatAsciiStringTag =
   5058       kStringTag | kOneByteStringTag | kSeqStringTag;
   5059   And(scratch, type, Operand(kFlatAsciiStringMask));
   5060   Branch(failure, ne, scratch, Operand(kFlatAsciiStringTag));
   5061 }
   5062 
   5063 
   5064 static const int kRegisterPassedArguments = 4;
   5065 
   5066 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
   5067                                               int num_double_arguments) {
   5068   int stack_passed_words = 0;
   5069   num_reg_arguments += 2 * num_double_arguments;
   5070 
   5071   // Up to four simple arguments are passed in registers a0..a3.
   5072   if (num_reg_arguments > kRegisterPassedArguments) {
   5073     stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
   5074   }
   5075   stack_passed_words += kCArgSlotCount;
   5076   return stack_passed_words;
   5077 }
   5078 
   5079 
   5080 void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
   5081                                                Register index,
   5082                                                Register value,
   5083                                                Register scratch,
   5084                                                uint32_t encoding_mask) {
   5085   Label is_object;
   5086   SmiTst(string, at);
   5087   Check(ne, kNonObject, at, Operand(zero_reg));
   5088 
   5089   lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
   5090   lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
   5091 
   5092   andi(at, at, kStringRepresentationMask | kStringEncodingMask);
   5093   li(scratch, Operand(encoding_mask));
   5094   Check(eq, kUnexpectedStringType, at, Operand(scratch));
   5095 
   5096   // The index is assumed to be untagged coming in, tag it to compare with the
   5097   // string length without using a temp register, it is restored at the end of
   5098   // this function.
   5099   Label index_tag_ok, index_tag_bad;
   5100   TrySmiTag(index, scratch, &index_tag_bad);
   5101   Branch(&index_tag_ok);
   5102   bind(&index_tag_bad);
   5103   Abort(kIndexIsTooLarge);
   5104   bind(&index_tag_ok);
   5105 
   5106   lw(at, FieldMemOperand(string, String::kLengthOffset));
   5107   Check(lt, kIndexIsTooLarge, index, Operand(at));
   5108 
   5109   ASSERT(Smi::FromInt(0) == 0);
   5110   Check(ge, kIndexIsNegative, index, Operand(zero_reg));
   5111 
   5112   SmiUntag(index, index);
   5113 }
   5114 
   5115 
   5116 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
   5117                                           int num_double_arguments,
   5118                                           Register scratch) {
   5119   int frame_alignment = ActivationFrameAlignment();
   5120 
   5121   // Up to four simple arguments are passed in registers a0..a3.
   5122   // Those four arguments must have reserved argument slots on the stack for
   5123   // mips, even though those argument slots are not normally used.
   5124   // Remaining arguments are pushed on the stack, above (higher address than)
   5125   // the argument slots.
   5126   int stack_passed_arguments = CalculateStackPassedWords(
   5127       num_reg_arguments, num_double_arguments);
   5128   if (frame_alignment > kPointerSize) {
   5129     // Make stack end at alignment and make room for num_arguments - 4 words
   5130     // and the original value of sp.
   5131     mov(scratch, sp);
   5132     Subu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
   5133     ASSERT(IsPowerOf2(frame_alignment));
   5134     And(sp, sp, Operand(-frame_alignment));
   5135     sw(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
   5136   } else {
   5137     Subu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
   5138   }
   5139 }
   5140 
   5141 
   5142 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
   5143                                           Register scratch) {
   5144   PrepareCallCFunction(num_reg_arguments, 0, scratch);
   5145 }
   5146 
   5147 
   5148 void MacroAssembler::CallCFunction(ExternalReference function,
   5149                                    int num_reg_arguments,
   5150                                    int num_double_arguments) {
   5151   li(t8, Operand(function));
   5152   CallCFunctionHelper(t8, num_reg_arguments, num_double_arguments);
   5153 }
   5154 
   5155 
   5156 void MacroAssembler::CallCFunction(Register function,
   5157                                    int num_reg_arguments,
   5158                                    int num_double_arguments) {
   5159   CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
   5160 }
   5161 
   5162 
   5163 void MacroAssembler::CallCFunction(ExternalReference function,
   5164                                    int num_arguments) {
   5165   CallCFunction(function, num_arguments, 0);
   5166 }
   5167 
   5168 
   5169 void MacroAssembler::CallCFunction(Register function,
   5170                                    int num_arguments) {
   5171   CallCFunction(function, num_arguments, 0);
   5172 }
   5173 
   5174 
   5175 void MacroAssembler::CallCFunctionHelper(Register function,
   5176                                          int num_reg_arguments,
   5177                                          int num_double_arguments) {
   5178   ASSERT(has_frame());
   5179   // Make sure that the stack is aligned before calling a C function unless
   5180   // running in the simulator. The simulator has its own alignment check which
   5181   // provides more information.
   5182   // The argument stots are presumed to have been set up by
   5183   // PrepareCallCFunction. The C function must be called via t9, for mips ABI.
   5184 
   5185 #if V8_HOST_ARCH_MIPS
   5186   if (emit_debug_code()) {
   5187     int frame_alignment = OS::ActivationFrameAlignment();
   5188     int frame_alignment_mask = frame_alignment - 1;
   5189     if (frame_alignment > kPointerSize) {
   5190       ASSERT(IsPowerOf2(frame_alignment));
   5191       Label alignment_as_expected;
   5192       And(at, sp, Operand(frame_alignment_mask));
   5193       Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
   5194       // Don't use Check here, as it will call Runtime_Abort possibly
   5195       // re-entering here.
   5196       stop("Unexpected alignment in CallCFunction");
   5197       bind(&alignment_as_expected);
   5198     }
   5199   }
   5200 #endif  // V8_HOST_ARCH_MIPS
   5201 
   5202   // Just call directly. The function called cannot cause a GC, or
   5203   // allow preemption, so the return address in the link register
   5204   // stays correct.
   5205 
   5206   if (!function.is(t9)) {
   5207     mov(t9, function);
   5208     function = t9;
   5209   }
   5210 
   5211   Call(function);
   5212 
   5213   int stack_passed_arguments = CalculateStackPassedWords(
   5214       num_reg_arguments, num_double_arguments);
   5215 
   5216   if (OS::ActivationFrameAlignment() > kPointerSize) {
   5217     lw(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
   5218   } else {
   5219     Addu(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize)));
   5220   }
   5221 }
   5222 
   5223 
   5224 #undef BRANCH_ARGS_CHECK
   5225 
   5226 
   5227 void MacroAssembler::PatchRelocatedValue(Register li_location,
   5228                                          Register scratch,
   5229                                          Register new_value) {
   5230   lw(scratch, MemOperand(li_location));
   5231   // At this point scratch is a lui(at, ...) instruction.
   5232   if (emit_debug_code()) {
   5233     And(scratch, scratch, kOpcodeMask);
   5234     Check(eq, kTheInstructionToPatchShouldBeALui,
   5235         scratch, Operand(LUI));
   5236     lw(scratch, MemOperand(li_location));
   5237   }
   5238   srl(t9, new_value, kImm16Bits);
   5239   Ins(scratch, t9, 0, kImm16Bits);
   5240   sw(scratch, MemOperand(li_location));
   5241 
   5242   lw(scratch, MemOperand(li_location, kInstrSize));
   5243   // scratch is now ori(at, ...).
   5244   if (emit_debug_code()) {
   5245     And(scratch, scratch, kOpcodeMask);
   5246     Check(eq, kTheInstructionToPatchShouldBeAnOri,
   5247         scratch, Operand(ORI));
   5248     lw(scratch, MemOperand(li_location, kInstrSize));
   5249   }
   5250   Ins(scratch, new_value, 0, kImm16Bits);
   5251   sw(scratch, MemOperand(li_location, kInstrSize));
   5252 
   5253   // Update the I-cache so the new lui and ori can be executed.
   5254   FlushICache(li_location, 2);
   5255 }
   5256 
   5257 void MacroAssembler::GetRelocatedValue(Register li_location,
   5258                                        Register value,
   5259                                        Register scratch) {
   5260   lw(value, MemOperand(li_location));
   5261   if (emit_debug_code()) {
   5262     And(value, value, kOpcodeMask);
   5263     Check(eq, kTheInstructionShouldBeALui,
   5264         value, Operand(LUI));
   5265     lw(value, MemOperand(li_location));
   5266   }
   5267 
   5268   // value now holds a lui instruction. Extract the immediate.
   5269   sll(value, value, kImm16Bits);
   5270 
   5271   lw(scratch, MemOperand(li_location, kInstrSize));
   5272   if (emit_debug_code()) {
   5273     And(scratch, scratch, kOpcodeMask);
   5274     Check(eq, kTheInstructionShouldBeAnOri,
   5275         scratch, Operand(ORI));
   5276     lw(scratch, MemOperand(li_location, kInstrSize));
   5277   }
   5278   // "scratch" now holds an ori instruction. Extract the immediate.
   5279   andi(scratch, scratch, kImm16Mask);
   5280 
   5281   // Merge the results.
   5282   or_(value, value, scratch);
   5283 }
   5284 
   5285 
   5286 void MacroAssembler::CheckPageFlag(
   5287     Register object,
   5288     Register scratch,
   5289     int mask,
   5290     Condition cc,
   5291     Label* condition_met) {
   5292   And(scratch, object, Operand(~Page::kPageAlignmentMask));
   5293   lw(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
   5294   And(scratch, scratch, Operand(mask));
   5295   Branch(condition_met, cc, scratch, Operand(zero_reg));
   5296 }
   5297 
   5298 
   5299 void MacroAssembler::CheckMapDeprecated(Handle<Map> map,
   5300                                         Register scratch,
   5301                                         Label* if_deprecated) {
   5302   if (map->CanBeDeprecated()) {
   5303     li(scratch, Operand(map));
   5304     lw(scratch, FieldMemOperand(scratch, Map::kBitField3Offset));
   5305     And(scratch, scratch, Operand(Map::Deprecated::kMask));
   5306     Branch(if_deprecated, ne, scratch, Operand(zero_reg));
   5307   }
   5308 }
   5309 
   5310 
   5311 void MacroAssembler::JumpIfBlack(Register object,
   5312                                  Register scratch0,
   5313                                  Register scratch1,
   5314                                  Label* on_black) {
   5315   HasColor(object, scratch0, scratch1, on_black, 1, 0);  // kBlackBitPattern.
   5316   ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
   5317 }
   5318 
   5319 
   5320 void MacroAssembler::HasColor(Register object,
   5321                               Register bitmap_scratch,
   5322                               Register mask_scratch,
   5323                               Label* has_color,
   5324                               int first_bit,
   5325                               int second_bit) {
   5326   ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t8));
   5327   ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t9));
   5328 
   5329   GetMarkBits(object, bitmap_scratch, mask_scratch);
   5330 
   5331   Label other_color, word_boundary;
   5332   lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   5333   And(t8, t9, Operand(mask_scratch));
   5334   Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg));
   5335   // Shift left 1 by adding.
   5336   Addu(mask_scratch, mask_scratch, Operand(mask_scratch));
   5337   Branch(&word_boundary, eq, mask_scratch, Operand(zero_reg));
   5338   And(t8, t9, Operand(mask_scratch));
   5339   Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg));
   5340   jmp(&other_color);
   5341 
   5342   bind(&word_boundary);
   5343   lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize));
   5344   And(t9, t9, Operand(1));
   5345   Branch(has_color, second_bit == 1 ? ne : eq, t9, Operand(zero_reg));
   5346   bind(&other_color);
   5347 }
   5348 
   5349 
   5350 // Detect some, but not all, common pointer-free objects.  This is used by the
   5351 // incremental write barrier which doesn't care about oddballs (they are always
   5352 // marked black immediately so this code is not hit).
   5353 void MacroAssembler::JumpIfDataObject(Register value,
   5354                                       Register scratch,
   5355                                       Label* not_data_object) {
   5356   ASSERT(!AreAliased(value, scratch, t8, no_reg));
   5357   Label is_data_object;
   5358   lw(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
   5359   LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
   5360   Branch(&is_data_object, eq, t8, Operand(scratch));
   5361   ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
   5362   ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
   5363   // If it's a string and it's not a cons string then it's an object containing
   5364   // no GC pointers.
   5365   lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   5366   And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask));
   5367   Branch(not_data_object, ne, t8, Operand(zero_reg));
   5368   bind(&is_data_object);
   5369 }
   5370 
   5371 
   5372 void MacroAssembler::GetMarkBits(Register addr_reg,
   5373                                  Register bitmap_reg,
   5374                                  Register mask_reg) {
   5375   ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
   5376   And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask));
   5377   Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2);
   5378   const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
   5379   Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits);
   5380   sll(t8, t8, kPointerSizeLog2);
   5381   Addu(bitmap_reg, bitmap_reg, t8);
   5382   li(t8, Operand(1));
   5383   sllv(mask_reg, t8, mask_reg);
   5384 }
   5385 
   5386 
   5387 void MacroAssembler::EnsureNotWhite(
   5388     Register value,
   5389     Register bitmap_scratch,
   5390     Register mask_scratch,
   5391     Register load_scratch,
   5392     Label* value_is_white_and_not_data) {
   5393   ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, t8));
   5394   GetMarkBits(value, bitmap_scratch, mask_scratch);
   5395 
   5396   // If the value is black or grey we don't need to do anything.
   5397   ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0);
   5398   ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
   5399   ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0);
   5400   ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
   5401 
   5402   Label done;
   5403 
   5404   // Since both black and grey have a 1 in the first position and white does
   5405   // not have a 1 there we only need to check one bit.
   5406   lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   5407   And(t8, mask_scratch, load_scratch);
   5408   Branch(&done, ne, t8, Operand(zero_reg));
   5409 
   5410   if (emit_debug_code()) {
   5411     // Check for impossible bit pattern.
   5412     Label ok;
   5413     // sll may overflow, making the check conservative.
   5414     sll(t8, mask_scratch, 1);
   5415     And(t8, load_scratch, t8);
   5416     Branch(&ok, eq, t8, Operand(zero_reg));
   5417     stop("Impossible marking bit pattern");
   5418     bind(&ok);
   5419   }
   5420 
   5421   // Value is white.  We check whether it is data that doesn't need scanning.
   5422   // Currently only checks for HeapNumber and non-cons strings.
   5423   Register map = load_scratch;  // Holds map while checking type.
   5424   Register length = load_scratch;  // Holds length of object after testing type.
   5425   Label is_data_object;
   5426 
   5427   // Check for heap-number
   5428   lw(map, FieldMemOperand(value, HeapObject::kMapOffset));
   5429   LoadRoot(t8, Heap::kHeapNumberMapRootIndex);
   5430   {
   5431     Label skip;
   5432     Branch(&skip, ne, t8, Operand(map));
   5433     li(length, HeapNumber::kSize);
   5434     Branch(&is_data_object);
   5435     bind(&skip);
   5436   }
   5437 
   5438   // Check for strings.
   5439   ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
   5440   ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
   5441   // If it's a string and it's not a cons string then it's an object containing
   5442   // no GC pointers.
   5443   Register instance_type = load_scratch;
   5444   lbu(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset));
   5445   And(t8, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask));
   5446   Branch(value_is_white_and_not_data, ne, t8, Operand(zero_reg));
   5447   // It's a non-indirect (non-cons and non-slice) string.
   5448   // If it's external, the length is just ExternalString::kSize.
   5449   // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
   5450   // External strings are the only ones with the kExternalStringTag bit
   5451   // set.
   5452   ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
   5453   ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
   5454   And(t8, instance_type, Operand(kExternalStringTag));
   5455   {
   5456     Label skip;
   5457     Branch(&skip, eq, t8, Operand(zero_reg));
   5458     li(length, ExternalString::kSize);
   5459     Branch(&is_data_object);
   5460     bind(&skip);
   5461   }
   5462 
   5463   // Sequential string, either ASCII or UC16.
   5464   // For ASCII (char-size of 1) we shift the smi tag away to get the length.
   5465   // For UC16 (char-size of 2) we just leave the smi tag in place, thereby
   5466   // getting the length multiplied by 2.
   5467   ASSERT(kOneByteStringTag == 4 && kStringEncodingMask == 4);
   5468   ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
   5469   lw(t9, FieldMemOperand(value, String::kLengthOffset));
   5470   And(t8, instance_type, Operand(kStringEncodingMask));
   5471   {
   5472     Label skip;
   5473     Branch(&skip, eq, t8, Operand(zero_reg));
   5474     srl(t9, t9, 1);
   5475     bind(&skip);
   5476   }
   5477   Addu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask));
   5478   And(length, length, Operand(~kObjectAlignmentMask));
   5479 
   5480   bind(&is_data_object);
   5481   // Value is a data object, and it is white.  Mark it black.  Since we know
   5482   // that the object is white we can make it black by flipping one bit.
   5483   lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   5484   Or(t8, t8, Operand(mask_scratch));
   5485   sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   5486 
   5487   And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask));
   5488   lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
   5489   Addu(t8, t8, Operand(length));
   5490   sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
   5491 
   5492   bind(&done);
   5493 }
   5494 
   5495 
   5496 void MacroAssembler::LoadInstanceDescriptors(Register map,
   5497                                              Register descriptors) {
   5498   lw(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
   5499 }
   5500 
   5501 
   5502 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
   5503   lw(dst, FieldMemOperand(map, Map::kBitField3Offset));
   5504   DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
   5505 }
   5506 
   5507 
   5508 void MacroAssembler::EnumLength(Register dst, Register map) {
   5509   STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
   5510   lw(dst, FieldMemOperand(map, Map::kBitField3Offset));
   5511   And(dst, dst, Operand(Map::EnumLengthBits::kMask));
   5512   SmiTag(dst);
   5513 }
   5514 
   5515 
   5516 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
   5517   Register  empty_fixed_array_value = t2;
   5518   LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
   5519   Label next, start;
   5520   mov(a2, a0);
   5521 
   5522   // Check if the enum length field is properly initialized, indicating that
   5523   // there is an enum cache.
   5524   lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
   5525 
   5526   EnumLength(a3, a1);
   5527   Branch(
   5528       call_runtime, eq, a3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel)));
   5529 
   5530   jmp(&start);
   5531 
   5532   bind(&next);
   5533   lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset));
   5534 
   5535   // For all objects but the receiver, check that the cache is empty.
   5536   EnumLength(a3, a1);
   5537   Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0)));
   5538 
   5539   bind(&start);
   5540 
   5541   // Check that there are no elements. Register a2 contains the current JS
   5542   // object we've reached through the prototype chain.
   5543   Label no_elements;
   5544   lw(a2, FieldMemOperand(a2, JSObject::kElementsOffset));
   5545   Branch(&no_elements, eq, a2, Operand(empty_fixed_array_value));
   5546 
   5547   // Second chance, the object may be using the empty slow element dictionary.
   5548   LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex);
   5549   Branch(call_runtime, ne, a2, Operand(at));
   5550 
   5551   bind(&no_elements);
   5552   lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset));
   5553   Branch(&next, ne, a2, Operand(null_value));
   5554 }
   5555 
   5556 
   5557 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
   5558   ASSERT(!output_reg.is(input_reg));
   5559   Label done;
   5560   li(output_reg, Operand(255));
   5561   // Normal branch: nop in delay slot.
   5562   Branch(&done, gt, input_reg, Operand(output_reg));
   5563   // Use delay slot in this branch.
   5564   Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg));
   5565   mov(output_reg, zero_reg);  // In delay slot.
   5566   mov(output_reg, input_reg);  // Value is in range 0..255.
   5567   bind(&done);
   5568 }
   5569 
   5570 
   5571 void MacroAssembler::ClampDoubleToUint8(Register result_reg,
   5572                                         DoubleRegister input_reg,
   5573                                         DoubleRegister temp_double_reg) {
   5574   Label above_zero;
   5575   Label done;
   5576   Label in_bounds;
   5577 
   5578   Move(temp_double_reg, 0.0);
   5579   BranchF(&above_zero, NULL, gt, input_reg, temp_double_reg);
   5580 
   5581   // Double value is less than zero, NaN or Inf, return 0.
   5582   mov(result_reg, zero_reg);
   5583   Branch(&done);
   5584 
   5585   // Double value is >= 255, return 255.
   5586   bind(&above_zero);
   5587   Move(temp_double_reg, 255.0);
   5588   BranchF(&in_bounds, NULL, le, input_reg, temp_double_reg);
   5589   li(result_reg, Operand(255));
   5590   Branch(&done);
   5591 
   5592   // In 0-255 range, round and truncate.
   5593   bind(&in_bounds);
   5594   cvt_w_d(temp_double_reg, input_reg);
   5595   mfc1(result_reg, temp_double_reg);
   5596   bind(&done);
   5597 }
   5598 
   5599 
   5600 void MacroAssembler::TestJSArrayForAllocationMemento(
   5601     Register receiver_reg,
   5602     Register scratch_reg,
   5603     Label* no_memento_found,
   5604     Condition cond,
   5605     Label* allocation_memento_present) {
   5606   ExternalReference new_space_start =
   5607       ExternalReference::new_space_start(isolate());
   5608   ExternalReference new_space_allocation_top =
   5609       ExternalReference::new_space_allocation_top_address(isolate());
   5610   Addu(scratch_reg, receiver_reg,
   5611        Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
   5612   Branch(no_memento_found, lt, scratch_reg, Operand(new_space_start));
   5613   li(at, Operand(new_space_allocation_top));
   5614   lw(at, MemOperand(at));
   5615   Branch(no_memento_found, gt, scratch_reg, Operand(at));
   5616   lw(scratch_reg, MemOperand(scratch_reg, -AllocationMemento::kSize));
   5617   if (allocation_memento_present) {
   5618     Branch(allocation_memento_present, cond, scratch_reg,
   5619            Operand(isolate()->factory()->allocation_memento_map()));
   5620   }
   5621 }
   5622 
   5623 
   5624 Register GetRegisterThatIsNotOneOf(Register reg1,
   5625                                    Register reg2,
   5626                                    Register reg3,
   5627                                    Register reg4,
   5628                                    Register reg5,
   5629                                    Register reg6) {
   5630   RegList regs = 0;
   5631   if (reg1.is_valid()) regs |= reg1.bit();
   5632   if (reg2.is_valid()) regs |= reg2.bit();
   5633   if (reg3.is_valid()) regs |= reg3.bit();
   5634   if (reg4.is_valid()) regs |= reg4.bit();
   5635   if (reg5.is_valid()) regs |= reg5.bit();
   5636   if (reg6.is_valid()) regs |= reg6.bit();
   5637 
   5638   for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
   5639     Register candidate = Register::FromAllocationIndex(i);
   5640     if (regs & candidate.bit()) continue;
   5641     return candidate;
   5642   }
   5643   UNREACHABLE();
   5644   return no_reg;
   5645 }
   5646 
   5647 
   5648 void MacroAssembler::JumpIfDictionaryInPrototypeChain(
   5649     Register object,
   5650     Register scratch0,
   5651     Register scratch1,
   5652     Label* found) {
   5653   ASSERT(!scratch1.is(scratch0));
   5654   Factory* factory = isolate()->factory();
   5655   Register current = scratch0;
   5656   Label loop_again;
   5657 
   5658   // Scratch contained elements pointer.
   5659   Move(current, object);
   5660 
   5661   // Loop based on the map going up the prototype chain.
   5662   bind(&loop_again);
   5663   lw(current, FieldMemOperand(current, HeapObject::kMapOffset));
   5664   lb(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
   5665   DecodeField<Map::ElementsKindBits>(scratch1);
   5666   Branch(found, eq, scratch1, Operand(DICTIONARY_ELEMENTS));
   5667   lw(current, FieldMemOperand(current, Map::kPrototypeOffset));
   5668   Branch(&loop_again, ne, current, Operand(factory->null_value()));
   5669 }
   5670 
   5671 
   5672 bool AreAliased(Register r1, Register r2, Register r3, Register r4) {
   5673   if (r1.is(r2)) return true;
   5674   if (r1.is(r3)) return true;
   5675   if (r1.is(r4)) return true;
   5676   if (r2.is(r3)) return true;
   5677   if (r2.is(r4)) return true;
   5678   if (r3.is(r4)) return true;
   5679   return false;
   5680 }
   5681 
   5682 
   5683 CodePatcher::CodePatcher(byte* address,
   5684                          int instructions,
   5685                          FlushICache flush_cache)
   5686     : address_(address),
   5687       size_(instructions * Assembler::kInstrSize),
   5688       masm_(NULL, address, size_ + Assembler::kGap),
   5689       flush_cache_(flush_cache) {
   5690   // Create a new macro assembler pointing to the address of the code to patch.
   5691   // The size is adjusted with kGap on order for the assembler to generate size
   5692   // bytes of instructions without failing with buffer size constraints.
   5693   ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   5694 }
   5695 
   5696 
   5697 CodePatcher::~CodePatcher() {
   5698   // Indicate that code has changed.
   5699   if (flush_cache_ == FLUSH) {
   5700     CPU::FlushICache(address_, size_);
   5701   }
   5702 
   5703   // Check that the code was patched as expected.
   5704   ASSERT(masm_.pc_ == address_ + size_);
   5705   ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   5706 }
   5707 
   5708 
   5709 void CodePatcher::Emit(Instr instr) {
   5710   masm()->emit(instr);
   5711 }
   5712 
   5713 
   5714 void CodePatcher::Emit(Address addr) {
   5715   masm()->emit(reinterpret_cast<Instr>(addr));
   5716 }
   5717 
   5718 
   5719 void CodePatcher::ChangeBranchCondition(Condition cond) {
   5720   Instr instr = Assembler::instr_at(masm_.pc_);
   5721   ASSERT(Assembler::IsBranch(instr));
   5722   uint32_t opcode = Assembler::GetOpcodeField(instr);
   5723   // Currently only the 'eq' and 'ne' cond values are supported and the simple
   5724   // branch instructions (with opcode being the branch type).
   5725   // There are some special cases (see Assembler::IsBranch()) so extending this
   5726   // would be tricky.
   5727   ASSERT(opcode == BEQ ||
   5728          opcode == BNE ||
   5729         opcode == BLEZ ||
   5730         opcode == BGTZ ||
   5731         opcode == BEQL ||
   5732         opcode == BNEL ||
   5733        opcode == BLEZL ||
   5734        opcode == BGTZL);
   5735   opcode = (cond == eq) ? BEQ : BNE;
   5736   instr = (instr & ~kOpcodeMask) | opcode;
   5737   masm_.emit(instr);
   5738 }
   5739 
   5740 
   5741 void MacroAssembler::TruncatingDiv(Register result,
   5742                                    Register dividend,
   5743                                    int32_t divisor) {
   5744   ASSERT(!dividend.is(result));
   5745   ASSERT(!dividend.is(at));
   5746   ASSERT(!result.is(at));
   5747   MultiplierAndShift ms(divisor);
   5748   li(at, Operand(ms.multiplier()));
   5749   Mult(dividend, Operand(at));
   5750   mfhi(result);
   5751   if (divisor > 0 && ms.multiplier() < 0) {
   5752     Addu(result, result, Operand(dividend));
   5753   }
   5754   if (divisor < 0 && ms.multiplier() > 0) {
   5755     Subu(result, result, Operand(dividend));
   5756   }
   5757   if (ms.shift() > 0) sra(result, result, ms.shift());
   5758   srl(at, dividend, 31);
   5759   Addu(result, result, Operand(at));
   5760 }
   5761 
   5762 
   5763 } }  // namespace v8::internal
   5764 
   5765 #endif  // V8_TARGET_ARCH_MIPS
   5766