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