Home | History | Annotate | Download | only in mips
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/mips/codegen-mips.h"
      6 
      7 #if V8_TARGET_ARCH_MIPS
      8 
      9 #include "src/codegen.h"
     10 #include "src/macro-assembler.h"
     11 #include "src/mips/simulator-mips.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 
     17 #define __ masm.
     18 
     19 
     20 #if defined(USE_SIMULATOR)
     21 byte* fast_exp_mips_machine_code = nullptr;
     22 double fast_exp_simulator(double x, Isolate* isolate) {
     23   return Simulator::current(isolate)->CallFP(fast_exp_mips_machine_code, x, 0);
     24 }
     25 #endif
     26 
     27 
     28 UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
     29   size_t actual_size;
     30   byte* buffer =
     31       static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
     32   if (buffer == nullptr) return nullptr;
     33   ExternalReference::InitializeMathExpData();
     34 
     35   MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
     36                       CodeObjectRequired::kNo);
     37 
     38   {
     39     DoubleRegister input = f12;
     40     DoubleRegister result = f0;
     41     DoubleRegister double_scratch1 = f4;
     42     DoubleRegister double_scratch2 = f6;
     43     Register temp1 = t0;
     44     Register temp2 = t1;
     45     Register temp3 = t2;
     46 
     47     __ MovFromFloatParameter(input);
     48     __ Push(temp3, temp2, temp1);
     49     MathExpGenerator::EmitMathExp(
     50         &masm, input, result, double_scratch1, double_scratch2,
     51         temp1, temp2, temp3);
     52     __ Pop(temp3, temp2, temp1);
     53     __ MovToFloatResult(result);
     54     __ Ret();
     55   }
     56 
     57   CodeDesc desc;
     58   masm.GetCode(&desc);
     59   DCHECK(!RelocInfo::RequiresRelocation(desc));
     60 
     61   Assembler::FlushICache(isolate, buffer, actual_size);
     62   base::OS::ProtectCode(buffer, actual_size);
     63 
     64 #if !defined(USE_SIMULATOR)
     65   return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
     66 #else
     67   fast_exp_mips_machine_code = buffer;
     68   return &fast_exp_simulator;
     69 #endif
     70 }
     71 
     72 
     73 #if defined(V8_HOST_ARCH_MIPS)
     74 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
     75                                                 MemCopyUint8Function stub) {
     76 #if defined(USE_SIMULATOR) || defined(_MIPS_ARCH_MIPS32R6) || \
     77     defined(_MIPS_ARCH_MIPS32RX)
     78   return stub;
     79 #else
     80   size_t actual_size;
     81   byte* buffer =
     82       static_cast<byte*>(base::OS::Allocate(3 * KB, &actual_size, true));
     83   if (buffer == nullptr) return stub;
     84 
     85   // This code assumes that cache lines are 32 bytes and if the cache line is
     86   // larger it will not work correctly.
     87   MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
     88                       CodeObjectRequired::kNo);
     89 
     90   {
     91     Label lastb, unaligned, aligned, chkw,
     92           loop16w, chk1w, wordCopy_loop, skip_pref, lastbloop,
     93           leave, ua_chk16w, ua_loop16w, ua_skip_pref, ua_chkw,
     94           ua_chk1w, ua_wordCopy_loop, ua_smallCopy, ua_smallCopy_loop;
     95 
     96     // The size of each prefetch.
     97     uint32_t pref_chunk = 32;
     98     // The maximum size of a prefetch, it must not be less then pref_chunk.
     99     // If the real size of a prefetch is greater then max_pref_size and
    100     // the kPrefHintPrepareForStore hint is used, the code will not work
    101     // correctly.
    102     uint32_t max_pref_size = 128;
    103     DCHECK(pref_chunk < max_pref_size);
    104 
    105     // pref_limit is set based on the fact that we never use an offset
    106     // greater then 5 on a store pref and that a single pref can
    107     // never be larger then max_pref_size.
    108     uint32_t pref_limit = (5 * pref_chunk) + max_pref_size;
    109     int32_t pref_hint_load = kPrefHintLoadStreamed;
    110     int32_t pref_hint_store = kPrefHintPrepareForStore;
    111     uint32_t loadstore_chunk = 4;
    112 
    113     // The initial prefetches may fetch bytes that are before the buffer being
    114     // copied. Start copies with an offset of 4 so avoid this situation when
    115     // using kPrefHintPrepareForStore.
    116     DCHECK(pref_hint_store != kPrefHintPrepareForStore ||
    117            pref_chunk * 4 >= max_pref_size);
    118 
    119     // If the size is less than 8, go to lastb. Regardless of size,
    120     // copy dst pointer to v0 for the retuen value.
    121     __ slti(t2, a2, 2 * loadstore_chunk);
    122     __ bne(t2, zero_reg, &lastb);
    123     __ mov(v0, a0);  // In delay slot.
    124 
    125     // If src and dst have different alignments, go to unaligned, if they
    126     // have the same alignment (but are not actually aligned) do a partial
    127     // load/store to make them aligned. If they are both already aligned
    128     // we can start copying at aligned.
    129     __ xor_(t8, a1, a0);
    130     __ andi(t8, t8, loadstore_chunk - 1);  // t8 is a0/a1 word-displacement.
    131     __ bne(t8, zero_reg, &unaligned);
    132     __ subu(a3, zero_reg, a0);  // In delay slot.
    133 
    134     __ andi(a3, a3, loadstore_chunk - 1);  // Copy a3 bytes to align a0/a1.
    135     __ beq(a3, zero_reg, &aligned);  // Already aligned.
    136     __ subu(a2, a2, a3);  // In delay slot. a2 is the remining bytes count.
    137 
    138     if (kArchEndian == kLittle) {
    139       __ lwr(t8, MemOperand(a1));
    140       __ addu(a1, a1, a3);
    141       __ swr(t8, MemOperand(a0));
    142       __ addu(a0, a0, a3);
    143     } else {
    144       __ lwl(t8, MemOperand(a1));
    145       __ addu(a1, a1, a3);
    146       __ swl(t8, MemOperand(a0));
    147       __ addu(a0, a0, a3);
    148     }
    149     // Now dst/src are both aligned to (word) aligned addresses. Set a2 to
    150     // count how many bytes we have to copy after all the 64 byte chunks are
    151     // copied and a3 to the dst pointer after all the 64 byte chunks have been
    152     // copied. We will loop, incrementing a0 and a1 until a0 equals a3.
    153     __ bind(&aligned);
    154     __ andi(t8, a2, 0x3f);
    155     __ beq(a2, t8, &chkw);  // Less than 64?
    156     __ subu(a3, a2, t8);  // In delay slot.
    157     __ addu(a3, a0, a3);  // Now a3 is the final dst after loop.
    158 
    159     // When in the loop we prefetch with kPrefHintPrepareForStore hint,
    160     // in this case the a0+x should be past the "t0-32" address. This means:
    161     // for x=128 the last "safe" a0 address is "t0-160". Alternatively, for
    162     // x=64 the last "safe" a0 address is "t0-96". In the current version we
    163     // will use "pref hint, 128(a0)", so "t0-160" is the limit.
    164     if (pref_hint_store == kPrefHintPrepareForStore) {
    165       __ addu(t0, a0, a2);  // t0 is the "past the end" address.
    166       __ Subu(t9, t0, pref_limit);  // t9 is the "last safe pref" address.
    167     }
    168 
    169     __ Pref(pref_hint_load, MemOperand(a1, 0 * pref_chunk));
    170     __ Pref(pref_hint_load, MemOperand(a1, 1 * pref_chunk));
    171     __ Pref(pref_hint_load, MemOperand(a1, 2 * pref_chunk));
    172     __ Pref(pref_hint_load, MemOperand(a1, 3 * pref_chunk));
    173 
    174     if (pref_hint_store != kPrefHintPrepareForStore) {
    175       __ Pref(pref_hint_store, MemOperand(a0, 1 * pref_chunk));
    176       __ Pref(pref_hint_store, MemOperand(a0, 2 * pref_chunk));
    177       __ Pref(pref_hint_store, MemOperand(a0, 3 * pref_chunk));
    178     }
    179     __ bind(&loop16w);
    180     __ lw(t0, MemOperand(a1));
    181 
    182     if (pref_hint_store == kPrefHintPrepareForStore) {
    183       __ sltu(v1, t9, a0);  // If a0 > t9, don't use next prefetch.
    184       __ Branch(USE_DELAY_SLOT, &skip_pref, gt, v1, Operand(zero_reg));
    185     }
    186     __ lw(t1, MemOperand(a1, 1, loadstore_chunk));  // Maybe in delay slot.
    187 
    188     __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk));
    189     __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk));
    190 
    191     __ bind(&skip_pref);
    192     __ lw(t2, MemOperand(a1, 2, loadstore_chunk));
    193     __ lw(t3, MemOperand(a1, 3, loadstore_chunk));
    194     __ lw(t4, MemOperand(a1, 4, loadstore_chunk));
    195     __ lw(t5, MemOperand(a1, 5, loadstore_chunk));
    196     __ lw(t6, MemOperand(a1, 6, loadstore_chunk));
    197     __ lw(t7, MemOperand(a1, 7, loadstore_chunk));
    198     __ Pref(pref_hint_load, MemOperand(a1, 4 * pref_chunk));
    199 
    200     __ sw(t0, MemOperand(a0));
    201     __ sw(t1, MemOperand(a0, 1, loadstore_chunk));
    202     __ sw(t2, MemOperand(a0, 2, loadstore_chunk));
    203     __ sw(t3, MemOperand(a0, 3, loadstore_chunk));
    204     __ sw(t4, MemOperand(a0, 4, loadstore_chunk));
    205     __ sw(t5, MemOperand(a0, 5, loadstore_chunk));
    206     __ sw(t6, MemOperand(a0, 6, loadstore_chunk));
    207     __ sw(t7, MemOperand(a0, 7, loadstore_chunk));
    208 
    209     __ lw(t0, MemOperand(a1, 8, loadstore_chunk));
    210     __ lw(t1, MemOperand(a1, 9, loadstore_chunk));
    211     __ lw(t2, MemOperand(a1, 10, loadstore_chunk));
    212     __ lw(t3, MemOperand(a1, 11, loadstore_chunk));
    213     __ lw(t4, MemOperand(a1, 12, loadstore_chunk));
    214     __ lw(t5, MemOperand(a1, 13, loadstore_chunk));
    215     __ lw(t6, MemOperand(a1, 14, loadstore_chunk));
    216     __ lw(t7, MemOperand(a1, 15, loadstore_chunk));
    217     __ Pref(pref_hint_load, MemOperand(a1, 5 * pref_chunk));
    218 
    219     __ sw(t0, MemOperand(a0, 8, loadstore_chunk));
    220     __ sw(t1, MemOperand(a0, 9, loadstore_chunk));
    221     __ sw(t2, MemOperand(a0, 10, loadstore_chunk));
    222     __ sw(t3, MemOperand(a0, 11, loadstore_chunk));
    223     __ sw(t4, MemOperand(a0, 12, loadstore_chunk));
    224     __ sw(t5, MemOperand(a0, 13, loadstore_chunk));
    225     __ sw(t6, MemOperand(a0, 14, loadstore_chunk));
    226     __ sw(t7, MemOperand(a0, 15, loadstore_chunk));
    227     __ addiu(a0, a0, 16 * loadstore_chunk);
    228     __ bne(a0, a3, &loop16w);
    229     __ addiu(a1, a1, 16 * loadstore_chunk);  // In delay slot.
    230     __ mov(a2, t8);
    231 
    232     // Here we have src and dest word-aligned but less than 64-bytes to go.
    233     // Check for a 32 bytes chunk and copy if there is one. Otherwise jump
    234     // down to chk1w to handle the tail end of the copy.
    235     __ bind(&chkw);
    236     __ Pref(pref_hint_load, MemOperand(a1, 0 * pref_chunk));
    237     __ andi(t8, a2, 0x1f);
    238     __ beq(a2, t8, &chk1w);  // Less than 32?
    239     __ nop();  // In delay slot.
    240     __ lw(t0, MemOperand(a1));
    241     __ lw(t1, MemOperand(a1, 1, loadstore_chunk));
    242     __ lw(t2, MemOperand(a1, 2, loadstore_chunk));
    243     __ lw(t3, MemOperand(a1, 3, loadstore_chunk));
    244     __ lw(t4, MemOperand(a1, 4, loadstore_chunk));
    245     __ lw(t5, MemOperand(a1, 5, loadstore_chunk));
    246     __ lw(t6, MemOperand(a1, 6, loadstore_chunk));
    247     __ lw(t7, MemOperand(a1, 7, loadstore_chunk));
    248     __ addiu(a1, a1, 8 * loadstore_chunk);
    249     __ sw(t0, MemOperand(a0));
    250     __ sw(t1, MemOperand(a0, 1, loadstore_chunk));
    251     __ sw(t2, MemOperand(a0, 2, loadstore_chunk));
    252     __ sw(t3, MemOperand(a0, 3, loadstore_chunk));
    253     __ sw(t4, MemOperand(a0, 4, loadstore_chunk));
    254     __ sw(t5, MemOperand(a0, 5, loadstore_chunk));
    255     __ sw(t6, MemOperand(a0, 6, loadstore_chunk));
    256     __ sw(t7, MemOperand(a0, 7, loadstore_chunk));
    257     __ addiu(a0, a0, 8 * loadstore_chunk);
    258 
    259     // Here we have less than 32 bytes to copy. Set up for a loop to copy
    260     // one word at a time. Set a2 to count how many bytes we have to copy
    261     // after all the word chunks are copied and a3 to the dst pointer after
    262     // all the word chunks have been copied. We will loop, incrementing a0
    263     // and a1 untill a0 equals a3.
    264     __ bind(&chk1w);
    265     __ andi(a2, t8, loadstore_chunk - 1);
    266     __ beq(a2, t8, &lastb);
    267     __ subu(a3, t8, a2);  // In delay slot.
    268     __ addu(a3, a0, a3);
    269 
    270     __ bind(&wordCopy_loop);
    271     __ lw(t3, MemOperand(a1));
    272     __ addiu(a0, a0, loadstore_chunk);
    273     __ addiu(a1, a1, loadstore_chunk);
    274     __ bne(a0, a3, &wordCopy_loop);
    275     __ sw(t3, MemOperand(a0, -1, loadstore_chunk));  // In delay slot.
    276 
    277     __ bind(&lastb);
    278     __ Branch(&leave, le, a2, Operand(zero_reg));
    279     __ addu(a3, a0, a2);
    280 
    281     __ bind(&lastbloop);
    282     __ lb(v1, MemOperand(a1));
    283     __ addiu(a0, a0, 1);
    284     __ addiu(a1, a1, 1);
    285     __ bne(a0, a3, &lastbloop);
    286     __ sb(v1, MemOperand(a0, -1));  // In delay slot.
    287 
    288     __ bind(&leave);
    289     __ jr(ra);
    290     __ nop();
    291 
    292     // Unaligned case. Only the dst gets aligned so we need to do partial
    293     // loads of the source followed by normal stores to the dst (once we
    294     // have aligned the destination).
    295     __ bind(&unaligned);
    296     __ andi(a3, a3, loadstore_chunk - 1);  // Copy a3 bytes to align a0/a1.
    297     __ beq(a3, zero_reg, &ua_chk16w);
    298     __ subu(a2, a2, a3);  // In delay slot.
    299 
    300     if (kArchEndian == kLittle) {
    301       __ lwr(v1, MemOperand(a1));
    302       __ lwl(v1,
    303              MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
    304       __ addu(a1, a1, a3);
    305       __ swr(v1, MemOperand(a0));
    306       __ addu(a0, a0, a3);
    307     } else {
    308       __ lwl(v1, MemOperand(a1));
    309       __ lwr(v1,
    310              MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
    311       __ addu(a1, a1, a3);
    312       __ swl(v1, MemOperand(a0));
    313       __ addu(a0, a0, a3);
    314     }
    315 
    316     // Now the dst (but not the source) is aligned. Set a2 to count how many
    317     // bytes we have to copy after all the 64 byte chunks are copied and a3 to
    318     // the dst pointer after all the 64 byte chunks have been copied. We will
    319     // loop, incrementing a0 and a1 until a0 equals a3.
    320     __ bind(&ua_chk16w);
    321     __ andi(t8, a2, 0x3f);
    322     __ beq(a2, t8, &ua_chkw);
    323     __ subu(a3, a2, t8);  // In delay slot.
    324     __ addu(a3, a0, a3);
    325 
    326     if (pref_hint_store == kPrefHintPrepareForStore) {
    327       __ addu(t0, a0, a2);
    328       __ Subu(t9, t0, pref_limit);
    329     }
    330 
    331     __ Pref(pref_hint_load, MemOperand(a1, 0 * pref_chunk));
    332     __ Pref(pref_hint_load, MemOperand(a1, 1 * pref_chunk));
    333     __ Pref(pref_hint_load, MemOperand(a1, 2 * pref_chunk));
    334 
    335     if (pref_hint_store != kPrefHintPrepareForStore) {
    336       __ Pref(pref_hint_store, MemOperand(a0, 1 * pref_chunk));
    337       __ Pref(pref_hint_store, MemOperand(a0, 2 * pref_chunk));
    338       __ Pref(pref_hint_store, MemOperand(a0, 3 * pref_chunk));
    339     }
    340 
    341     __ bind(&ua_loop16w);
    342     __ Pref(pref_hint_load, MemOperand(a1, 3 * pref_chunk));
    343     if (kArchEndian == kLittle) {
    344       __ lwr(t0, MemOperand(a1));
    345       __ lwr(t1, MemOperand(a1, 1, loadstore_chunk));
    346       __ lwr(t2, MemOperand(a1, 2, loadstore_chunk));
    347 
    348       if (pref_hint_store == kPrefHintPrepareForStore) {
    349         __ sltu(v1, t9, a0);
    350         __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg));
    351       }
    352       __ lwr(t3, MemOperand(a1, 3, loadstore_chunk));  // Maybe in delay slot.
    353 
    354       __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk));
    355       __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk));
    356 
    357       __ bind(&ua_skip_pref);
    358       __ lwr(t4, MemOperand(a1, 4, loadstore_chunk));
    359       __ lwr(t5, MemOperand(a1, 5, loadstore_chunk));
    360       __ lwr(t6, MemOperand(a1, 6, loadstore_chunk));
    361       __ lwr(t7, MemOperand(a1, 7, loadstore_chunk));
    362       __ lwl(t0,
    363              MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
    364       __ lwl(t1,
    365              MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
    366       __ lwl(t2,
    367              MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
    368       __ lwl(t3,
    369              MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
    370       __ lwl(t4,
    371              MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
    372       __ lwl(t5,
    373              MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
    374       __ lwl(t6,
    375              MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
    376       __ lwl(t7,
    377              MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
    378     } else {
    379       __ lwl(t0, MemOperand(a1));
    380       __ lwl(t1, MemOperand(a1, 1, loadstore_chunk));
    381       __ lwl(t2, MemOperand(a1, 2, loadstore_chunk));
    382 
    383       if (pref_hint_store == kPrefHintPrepareForStore) {
    384         __ sltu(v1, t9, a0);
    385         __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg));
    386       }
    387       __ lwl(t3, MemOperand(a1, 3, loadstore_chunk));  // Maybe in delay slot.
    388 
    389       __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk));
    390       __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk));
    391 
    392       __ bind(&ua_skip_pref);
    393       __ lwl(t4, MemOperand(a1, 4, loadstore_chunk));
    394       __ lwl(t5, MemOperand(a1, 5, loadstore_chunk));
    395       __ lwl(t6, MemOperand(a1, 6, loadstore_chunk));
    396       __ lwl(t7, MemOperand(a1, 7, loadstore_chunk));
    397       __ lwr(t0,
    398              MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
    399       __ lwr(t1,
    400              MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
    401       __ lwr(t2,
    402              MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
    403       __ lwr(t3,
    404              MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
    405       __ lwr(t4,
    406              MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
    407       __ lwr(t5,
    408              MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
    409       __ lwr(t6,
    410              MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
    411       __ lwr(t7,
    412              MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
    413     }
    414     __ Pref(pref_hint_load, MemOperand(a1, 4 * pref_chunk));
    415     __ sw(t0, MemOperand(a0));
    416     __ sw(t1, MemOperand(a0, 1, loadstore_chunk));
    417     __ sw(t2, MemOperand(a0, 2, loadstore_chunk));
    418     __ sw(t3, MemOperand(a0, 3, loadstore_chunk));
    419     __ sw(t4, MemOperand(a0, 4, loadstore_chunk));
    420     __ sw(t5, MemOperand(a0, 5, loadstore_chunk));
    421     __ sw(t6, MemOperand(a0, 6, loadstore_chunk));
    422     __ sw(t7, MemOperand(a0, 7, loadstore_chunk));
    423     if (kArchEndian == kLittle) {
    424       __ lwr(t0, MemOperand(a1, 8, loadstore_chunk));
    425       __ lwr(t1, MemOperand(a1, 9, loadstore_chunk));
    426       __ lwr(t2, MemOperand(a1, 10, loadstore_chunk));
    427       __ lwr(t3, MemOperand(a1, 11, loadstore_chunk));
    428       __ lwr(t4, MemOperand(a1, 12, loadstore_chunk));
    429       __ lwr(t5, MemOperand(a1, 13, loadstore_chunk));
    430       __ lwr(t6, MemOperand(a1, 14, loadstore_chunk));
    431       __ lwr(t7, MemOperand(a1, 15, loadstore_chunk));
    432       __ lwl(t0,
    433              MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one));
    434       __ lwl(t1,
    435              MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one));
    436       __ lwl(t2,
    437              MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one));
    438       __ lwl(t3,
    439              MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one));
    440       __ lwl(t4,
    441              MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one));
    442       __ lwl(t5,
    443              MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one));
    444       __ lwl(t6,
    445              MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one));
    446       __ lwl(t7,
    447              MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one));
    448     } else {
    449       __ lwl(t0, MemOperand(a1, 8, loadstore_chunk));
    450       __ lwl(t1, MemOperand(a1, 9, loadstore_chunk));
    451       __ lwl(t2, MemOperand(a1, 10, loadstore_chunk));
    452       __ lwl(t3, MemOperand(a1, 11, loadstore_chunk));
    453       __ lwl(t4, MemOperand(a1, 12, loadstore_chunk));
    454       __ lwl(t5, MemOperand(a1, 13, loadstore_chunk));
    455       __ lwl(t6, MemOperand(a1, 14, loadstore_chunk));
    456       __ lwl(t7, MemOperand(a1, 15, loadstore_chunk));
    457       __ lwr(t0,
    458              MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one));
    459       __ lwr(t1,
    460              MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one));
    461       __ lwr(t2,
    462              MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one));
    463       __ lwr(t3,
    464              MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one));
    465       __ lwr(t4,
    466              MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one));
    467       __ lwr(t5,
    468              MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one));
    469       __ lwr(t6,
    470              MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one));
    471       __ lwr(t7,
    472              MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one));
    473     }
    474     __ Pref(pref_hint_load, MemOperand(a1, 5 * pref_chunk));
    475     __ sw(t0, MemOperand(a0, 8, loadstore_chunk));
    476     __ sw(t1, MemOperand(a0, 9, loadstore_chunk));
    477     __ sw(t2, MemOperand(a0, 10, loadstore_chunk));
    478     __ sw(t3, MemOperand(a0, 11, loadstore_chunk));
    479     __ sw(t4, MemOperand(a0, 12, loadstore_chunk));
    480     __ sw(t5, MemOperand(a0, 13, loadstore_chunk));
    481     __ sw(t6, MemOperand(a0, 14, loadstore_chunk));
    482     __ sw(t7, MemOperand(a0, 15, loadstore_chunk));
    483     __ addiu(a0, a0, 16 * loadstore_chunk);
    484     __ bne(a0, a3, &ua_loop16w);
    485     __ addiu(a1, a1, 16 * loadstore_chunk);  // In delay slot.
    486     __ mov(a2, t8);
    487 
    488     // Here less than 64-bytes. Check for
    489     // a 32 byte chunk and copy if there is one. Otherwise jump down to
    490     // ua_chk1w to handle the tail end of the copy.
    491     __ bind(&ua_chkw);
    492     __ Pref(pref_hint_load, MemOperand(a1));
    493     __ andi(t8, a2, 0x1f);
    494 
    495     __ beq(a2, t8, &ua_chk1w);
    496     __ nop();  // In delay slot.
    497     if (kArchEndian == kLittle) {
    498       __ lwr(t0, MemOperand(a1));
    499       __ lwr(t1, MemOperand(a1, 1, loadstore_chunk));
    500       __ lwr(t2, MemOperand(a1, 2, loadstore_chunk));
    501       __ lwr(t3, MemOperand(a1, 3, loadstore_chunk));
    502       __ lwr(t4, MemOperand(a1, 4, loadstore_chunk));
    503       __ lwr(t5, MemOperand(a1, 5, loadstore_chunk));
    504       __ lwr(t6, MemOperand(a1, 6, loadstore_chunk));
    505       __ lwr(t7, MemOperand(a1, 7, loadstore_chunk));
    506       __ lwl(t0,
    507              MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
    508       __ lwl(t1,
    509              MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
    510       __ lwl(t2,
    511              MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
    512       __ lwl(t3,
    513              MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
    514       __ lwl(t4,
    515              MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
    516       __ lwl(t5,
    517              MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
    518       __ lwl(t6,
    519              MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
    520       __ lwl(t7,
    521              MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
    522     } else {
    523       __ lwl(t0, MemOperand(a1));
    524       __ lwl(t1, MemOperand(a1, 1, loadstore_chunk));
    525       __ lwl(t2, MemOperand(a1, 2, loadstore_chunk));
    526       __ lwl(t3, MemOperand(a1, 3, loadstore_chunk));
    527       __ lwl(t4, MemOperand(a1, 4, loadstore_chunk));
    528       __ lwl(t5, MemOperand(a1, 5, loadstore_chunk));
    529       __ lwl(t6, MemOperand(a1, 6, loadstore_chunk));
    530       __ lwl(t7, MemOperand(a1, 7, loadstore_chunk));
    531       __ lwr(t0,
    532              MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
    533       __ lwr(t1,
    534              MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
    535       __ lwr(t2,
    536              MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
    537       __ lwr(t3,
    538              MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
    539       __ lwr(t4,
    540              MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
    541       __ lwr(t5,
    542              MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
    543       __ lwr(t6,
    544              MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
    545       __ lwr(t7,
    546              MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
    547     }
    548     __ addiu(a1, a1, 8 * loadstore_chunk);
    549     __ sw(t0, MemOperand(a0));
    550     __ sw(t1, MemOperand(a0, 1, loadstore_chunk));
    551     __ sw(t2, MemOperand(a0, 2, loadstore_chunk));
    552     __ sw(t3, MemOperand(a0, 3, loadstore_chunk));
    553     __ sw(t4, MemOperand(a0, 4, loadstore_chunk));
    554     __ sw(t5, MemOperand(a0, 5, loadstore_chunk));
    555     __ sw(t6, MemOperand(a0, 6, loadstore_chunk));
    556     __ sw(t7, MemOperand(a0, 7, loadstore_chunk));
    557     __ addiu(a0, a0, 8 * loadstore_chunk);
    558 
    559     // Less than 32 bytes to copy. Set up for a loop to
    560     // copy one word at a time.
    561     __ bind(&ua_chk1w);
    562     __ andi(a2, t8, loadstore_chunk - 1);
    563     __ beq(a2, t8, &ua_smallCopy);
    564     __ subu(a3, t8, a2);  // In delay slot.
    565     __ addu(a3, a0, a3);
    566 
    567     __ bind(&ua_wordCopy_loop);
    568     if (kArchEndian == kLittle) {
    569       __ lwr(v1, MemOperand(a1));
    570       __ lwl(v1,
    571              MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
    572     } else {
    573       __ lwl(v1, MemOperand(a1));
    574       __ lwr(v1,
    575              MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
    576     }
    577     __ addiu(a0, a0, loadstore_chunk);
    578     __ addiu(a1, a1, loadstore_chunk);
    579     __ bne(a0, a3, &ua_wordCopy_loop);
    580     __ sw(v1, MemOperand(a0, -1, loadstore_chunk));  // In delay slot.
    581 
    582     // Copy the last 8 bytes.
    583     __ bind(&ua_smallCopy);
    584     __ beq(a2, zero_reg, &leave);
    585     __ addu(a3, a0, a2);  // In delay slot.
    586 
    587     __ bind(&ua_smallCopy_loop);
    588     __ lb(v1, MemOperand(a1));
    589     __ addiu(a0, a0, 1);
    590     __ addiu(a1, a1, 1);
    591     __ bne(a0, a3, &ua_smallCopy_loop);
    592     __ sb(v1, MemOperand(a0, -1));  // In delay slot.
    593 
    594     __ jr(ra);
    595     __ nop();
    596   }
    597   CodeDesc desc;
    598   masm.GetCode(&desc);
    599   DCHECK(!RelocInfo::RequiresRelocation(desc));
    600 
    601   Assembler::FlushICache(isolate, buffer, actual_size);
    602   base::OS::ProtectCode(buffer, actual_size);
    603   return FUNCTION_CAST<MemCopyUint8Function>(buffer);
    604 #endif
    605 }
    606 #endif
    607 
    608 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
    609 #if defined(USE_SIMULATOR)
    610   return nullptr;
    611 #else
    612   size_t actual_size;
    613   byte* buffer =
    614       static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
    615   if (buffer == nullptr) return nullptr;
    616 
    617   MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
    618                       CodeObjectRequired::kNo);
    619 
    620   __ MovFromFloatParameter(f12);
    621   __ sqrt_d(f0, f12);
    622   __ MovToFloatResult(f0);
    623   __ Ret();
    624 
    625   CodeDesc desc;
    626   masm.GetCode(&desc);
    627   DCHECK(!RelocInfo::RequiresRelocation(desc));
    628 
    629   Assembler::FlushICache(isolate, buffer, actual_size);
    630   base::OS::ProtectCode(buffer, actual_size);
    631   return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
    632 #endif
    633 }
    634 
    635 #undef __
    636 
    637 
    638 // -------------------------------------------------------------------------
    639 // Platform-specific RuntimeCallHelper functions.
    640 
    641 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
    642   masm->EnterFrame(StackFrame::INTERNAL);
    643   DCHECK(!masm->has_frame());
    644   masm->set_has_frame(true);
    645 }
    646 
    647 
    648 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
    649   masm->LeaveFrame(StackFrame::INTERNAL);
    650   DCHECK(masm->has_frame());
    651   masm->set_has_frame(false);
    652 }
    653 
    654 
    655 // -------------------------------------------------------------------------
    656 // Code generators
    657 
    658 #define __ ACCESS_MASM(masm)
    659 
    660 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
    661     MacroAssembler* masm,
    662     Register receiver,
    663     Register key,
    664     Register value,
    665     Register target_map,
    666     AllocationSiteMode mode,
    667     Label* allocation_memento_found) {
    668   Register scratch_elements = t0;
    669   DCHECK(!AreAliased(receiver, key, value, target_map,
    670                      scratch_elements));
    671 
    672   if (mode == TRACK_ALLOCATION_SITE) {
    673     DCHECK(allocation_memento_found != NULL);
    674     __ JumpIfJSArrayHasAllocationMemento(
    675         receiver, scratch_elements, allocation_memento_found);
    676   }
    677 
    678   // Set transitioned map.
    679   __ sw(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
    680   __ RecordWriteField(receiver,
    681                       HeapObject::kMapOffset,
    682                       target_map,
    683                       t5,
    684                       kRAHasNotBeenSaved,
    685                       kDontSaveFPRegs,
    686                       EMIT_REMEMBERED_SET,
    687                       OMIT_SMI_CHECK);
    688 }
    689 
    690 
    691 void ElementsTransitionGenerator::GenerateSmiToDouble(
    692     MacroAssembler* masm,
    693     Register receiver,
    694     Register key,
    695     Register value,
    696     Register target_map,
    697     AllocationSiteMode mode,
    698     Label* fail) {
    699   // Register ra contains the return address.
    700   Label loop, entry, convert_hole, gc_required, only_change_map, done;
    701   Register elements = t0;
    702   Register length = t1;
    703   Register array = t2;
    704   Register array_end = array;
    705 
    706   // target_map parameter can be clobbered.
    707   Register scratch1 = target_map;
    708   Register scratch2 = t5;
    709   Register scratch3 = t3;
    710 
    711   // Verify input registers don't conflict with locals.
    712   DCHECK(!AreAliased(receiver, key, value, target_map,
    713                      elements, length, array, scratch2));
    714 
    715   Register scratch = t6;
    716 
    717   if (mode == TRACK_ALLOCATION_SITE) {
    718     __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
    719   }
    720 
    721   // Check for empty arrays, which only require a map transition and no changes
    722   // to the backing store.
    723   __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
    724   __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
    725   __ Branch(&only_change_map, eq, at, Operand(elements));
    726 
    727   __ push(ra);
    728   __ lw(length, FieldMemOperand(elements, FixedArray::kLengthOffset));
    729   // elements: source FixedArray
    730   // length: number of elements (smi-tagged)
    731 
    732   // Allocate new FixedDoubleArray.
    733   __ sll(scratch, length, 2);
    734   __ Addu(scratch, scratch, FixedDoubleArray::kHeaderSize);
    735   __ Allocate(scratch, array, t3, scratch2, &gc_required, DOUBLE_ALIGNMENT);
    736   // array: destination FixedDoubleArray, not tagged as heap object
    737 
    738   // Set destination FixedDoubleArray's length and map.
    739   __ LoadRoot(scratch2, Heap::kFixedDoubleArrayMapRootIndex);
    740   __ sw(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
    741   // Update receiver's map.
    742   __ sw(scratch2, MemOperand(array, HeapObject::kMapOffset));
    743 
    744   __ sw(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
    745   __ RecordWriteField(receiver,
    746                       HeapObject::kMapOffset,
    747                       target_map,
    748                       scratch2,
    749                       kRAHasBeenSaved,
    750                       kDontSaveFPRegs,
    751                       OMIT_REMEMBERED_SET,
    752                       OMIT_SMI_CHECK);
    753   // Replace receiver's backing store with newly created FixedDoubleArray.
    754   __ Addu(scratch1, array, Operand(kHeapObjectTag));
    755   __ sw(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset));
    756   __ RecordWriteField(receiver,
    757                       JSObject::kElementsOffset,
    758                       scratch1,
    759                       scratch2,
    760                       kRAHasBeenSaved,
    761                       kDontSaveFPRegs,
    762                       EMIT_REMEMBERED_SET,
    763                       OMIT_SMI_CHECK);
    764 
    765 
    766   // Prepare for conversion loop.
    767   __ Addu(scratch1, elements,
    768       Operand(FixedArray::kHeaderSize - kHeapObjectTag));
    769   __ Addu(scratch3, array, Operand(FixedDoubleArray::kHeaderSize));
    770   __ sll(at, length, 2);
    771   __ Addu(array_end, scratch3, at);
    772 
    773   // Repurpose registers no longer in use.
    774   Register hole_lower = elements;
    775   Register hole_upper = length;
    776   __ li(hole_lower, Operand(kHoleNanLower32));
    777   __ li(hole_upper, Operand(kHoleNanUpper32));
    778 
    779   // scratch1: begin of source FixedArray element fields, not tagged
    780   // hole_lower: kHoleNanLower32
    781   // hole_upper: kHoleNanUpper32
    782   // array_end: end of destination FixedDoubleArray, not tagged
    783   // scratch3: begin of FixedDoubleArray element fields, not tagged
    784 
    785   __ Branch(&entry);
    786 
    787   __ bind(&only_change_map);
    788   __ sw(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
    789   __ RecordWriteField(receiver,
    790                       HeapObject::kMapOffset,
    791                       target_map,
    792                       scratch2,
    793                       kRAHasBeenSaved,
    794                       kDontSaveFPRegs,
    795                       OMIT_REMEMBERED_SET,
    796                       OMIT_SMI_CHECK);
    797   __ Branch(&done);
    798 
    799   // Call into runtime if GC is required.
    800   __ bind(&gc_required);
    801   __ lw(ra, MemOperand(sp, 0));
    802   __ Branch(USE_DELAY_SLOT, fail);
    803   __ addiu(sp, sp, kPointerSize);  // In delay slot.
    804 
    805   // Convert and copy elements.
    806   __ bind(&loop);
    807   __ lw(scratch2, MemOperand(scratch1));
    808   __ Addu(scratch1, scratch1, kIntSize);
    809   // scratch2: current element
    810   __ UntagAndJumpIfNotSmi(scratch2, scratch2, &convert_hole);
    811 
    812   // Normal smi, convert to double and store.
    813   __ mtc1(scratch2, f0);
    814   __ cvt_d_w(f0, f0);
    815   __ sdc1(f0, MemOperand(scratch3));
    816   __ Branch(USE_DELAY_SLOT, &entry);
    817   __ addiu(scratch3, scratch3, kDoubleSize);  // In delay slot.
    818 
    819   // Hole found, store the-hole NaN.
    820   __ bind(&convert_hole);
    821   if (FLAG_debug_code) {
    822     // Restore a "smi-untagged" heap object.
    823     __ SmiTag(scratch2);
    824     __ Or(scratch2, scratch2, Operand(1));
    825     __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
    826     __ Assert(eq, kObjectFoundInSmiOnlyArray, at, Operand(scratch2));
    827   }
    828   // mantissa
    829   __ sw(hole_lower, MemOperand(scratch3, Register::kMantissaOffset));
    830   // exponent
    831   __ sw(hole_upper, MemOperand(scratch3, Register::kExponentOffset));
    832   __ addiu(scratch3, scratch3, kDoubleSize);
    833 
    834   __ bind(&entry);
    835   __ Branch(&loop, lt, scratch3, Operand(array_end));
    836 
    837   __ bind(&done);
    838   __ pop(ra);
    839 }
    840 
    841 
    842 void ElementsTransitionGenerator::GenerateDoubleToObject(
    843     MacroAssembler* masm,
    844     Register receiver,
    845     Register key,
    846     Register value,
    847     Register target_map,
    848     AllocationSiteMode mode,
    849     Label* fail) {
    850   // Register ra contains the return address.
    851   Label entry, loop, convert_hole, gc_required, only_change_map;
    852   Register elements = t0;
    853   Register array = t2;
    854   Register length = t1;
    855   Register scratch = t5;
    856 
    857   // Verify input registers don't conflict with locals.
    858   DCHECK(!AreAliased(receiver, key, value, target_map,
    859                      elements, array, length, scratch));
    860 
    861   if (mode == TRACK_ALLOCATION_SITE) {
    862     __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
    863   }
    864 
    865   // Check for empty arrays, which only require a map transition and no changes
    866   // to the backing store.
    867   __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
    868   __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
    869   __ Branch(&only_change_map, eq, at, Operand(elements));
    870 
    871   __ MultiPush(
    872       value.bit() | key.bit() | receiver.bit() | target_map.bit() | ra.bit());
    873 
    874   __ lw(length, FieldMemOperand(elements, FixedArray::kLengthOffset));
    875   // elements: source FixedArray
    876   // length: number of elements (smi-tagged)
    877 
    878   // Allocate new FixedArray.
    879   // Re-use value and target_map registers, as they have been saved on the
    880   // stack.
    881   Register array_size = value;
    882   Register allocate_scratch = target_map;
    883   __ sll(array_size, length, 1);
    884   __ Addu(array_size, array_size, FixedDoubleArray::kHeaderSize);
    885   __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required,
    886               NO_ALLOCATION_FLAGS);
    887   // array: destination FixedArray, not tagged as heap object
    888   // Set destination FixedDoubleArray's length and map.
    889   __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
    890   __ sw(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
    891   __ sw(scratch, MemOperand(array, HeapObject::kMapOffset));
    892 
    893   // Prepare for conversion loop.
    894   Register src_elements = elements;
    895   Register dst_elements = target_map;
    896   Register dst_end = length;
    897   Register heap_number_map = scratch;
    898   __ Addu(src_elements, src_elements, Operand(
    899         FixedDoubleArray::kHeaderSize - kHeapObjectTag
    900         + Register::kExponentOffset));
    901   __ Addu(dst_elements, array, Operand(FixedArray::kHeaderSize));
    902   __ sll(dst_end, dst_end, 1);
    903   __ Addu(dst_end, dst_elements, dst_end);
    904 
    905   // Allocating heap numbers in the loop below can fail and cause a jump to
    906   // gc_required. We can't leave a partly initialized FixedArray behind,
    907   // so pessimistically fill it with holes now.
    908   Label initialization_loop, initialization_loop_entry;
    909   __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
    910   __ Branch(&initialization_loop_entry);
    911   __ bind(&initialization_loop);
    912   __ sw(scratch, MemOperand(dst_elements));
    913   __ Addu(dst_elements, dst_elements, Operand(kPointerSize));
    914   __ bind(&initialization_loop_entry);
    915   __ Branch(&initialization_loop, lt, dst_elements, Operand(dst_end));
    916 
    917   __ Addu(dst_elements, array, Operand(FixedArray::kHeaderSize));
    918   __ Addu(array, array, Operand(kHeapObjectTag));
    919   __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
    920   // Using offsetted addresses.
    921   // dst_elements: begin of destination FixedArray element fields, not tagged
    922   // src_elements: begin of source FixedDoubleArray element fields, not tagged,
    923   //               points to the exponent
    924   // dst_end: end of destination FixedArray, not tagged
    925   // array: destination FixedArray
    926   // heap_number_map: heap number map
    927   __ Branch(&entry);
    928 
    929   // Call into runtime if GC is required.
    930   __ bind(&gc_required);
    931   __ MultiPop(
    932       value.bit() | key.bit() | receiver.bit() | target_map.bit() | ra.bit());
    933 
    934   __ Branch(fail);
    935 
    936   __ bind(&loop);
    937   Register upper_bits = key;
    938   __ lw(upper_bits, MemOperand(src_elements));
    939   __ Addu(src_elements, src_elements, kDoubleSize);
    940   // upper_bits: current element's upper 32 bit
    941   // src_elements: address of next element's upper 32 bit
    942   __ Branch(&convert_hole, eq, a1, Operand(kHoleNanUpper32));
    943 
    944   // Non-hole double, copy value into a heap number.
    945   Register heap_number = receiver;
    946   Register scratch2 = value;
    947   Register scratch3 = t6;
    948   __ AllocateHeapNumber(heap_number, scratch2, scratch3, heap_number_map,
    949                         &gc_required);
    950   // heap_number: new heap number
    951   // Load mantissa of current element, src_elements
    952   // point to exponent of next element.
    953   __ lw(scratch2, MemOperand(src_elements, (Register::kMantissaOffset
    954       - Register::kExponentOffset - kDoubleSize)));
    955   __ sw(scratch2, FieldMemOperand(heap_number, HeapNumber::kMantissaOffset));
    956   __ sw(upper_bits, FieldMemOperand(heap_number, HeapNumber::kExponentOffset));
    957   __ mov(scratch2, dst_elements);
    958   __ sw(heap_number, MemOperand(dst_elements));
    959   __ Addu(dst_elements, dst_elements, kIntSize);
    960   __ RecordWrite(array,
    961                  scratch2,
    962                  heap_number,
    963                  kRAHasBeenSaved,
    964                  kDontSaveFPRegs,
    965                  EMIT_REMEMBERED_SET,
    966                  OMIT_SMI_CHECK);
    967   __ Branch(&entry);
    968 
    969   // Replace the-hole NaN with the-hole pointer.
    970   __ bind(&convert_hole);
    971   __ LoadRoot(scratch2, Heap::kTheHoleValueRootIndex);
    972   __ sw(scratch2, MemOperand(dst_elements));
    973   __ Addu(dst_elements, dst_elements, kIntSize);
    974 
    975   __ bind(&entry);
    976   __ Branch(&loop, lt, dst_elements, Operand(dst_end));
    977 
    978   __ MultiPop(receiver.bit() | target_map.bit() | value.bit() | key.bit());
    979   // Replace receiver's backing store with newly created and filled FixedArray.
    980   __ sw(array, FieldMemOperand(receiver, JSObject::kElementsOffset));
    981   __ RecordWriteField(receiver,
    982                       JSObject::kElementsOffset,
    983                       array,
    984                       scratch,
    985                       kRAHasBeenSaved,
    986                       kDontSaveFPRegs,
    987                       EMIT_REMEMBERED_SET,
    988                       OMIT_SMI_CHECK);
    989   __ pop(ra);
    990 
    991   __ bind(&only_change_map);
    992   // Update receiver's map.
    993   __ sw(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
    994   __ RecordWriteField(receiver,
    995                       HeapObject::kMapOffset,
    996                       target_map,
    997                       scratch,
    998                       kRAHasNotBeenSaved,
    999                       kDontSaveFPRegs,
   1000                       OMIT_REMEMBERED_SET,
   1001                       OMIT_SMI_CHECK);
   1002 }
   1003 
   1004 
   1005 void StringCharLoadGenerator::Generate(MacroAssembler* masm,
   1006                                        Register string,
   1007                                        Register index,
   1008                                        Register result,
   1009                                        Label* call_runtime) {
   1010   // Fetch the instance type of the receiver into result register.
   1011   __ lw(result, FieldMemOperand(string, HeapObject::kMapOffset));
   1012   __ lbu(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
   1013 
   1014   // We need special handling for indirect strings.
   1015   Label check_sequential;
   1016   __ And(at, result, Operand(kIsIndirectStringMask));
   1017   __ Branch(&check_sequential, eq, at, Operand(zero_reg));
   1018 
   1019   // Dispatch on the indirect string shape: slice or cons.
   1020   Label cons_string;
   1021   __ And(at, result, Operand(kSlicedNotConsMask));
   1022   __ Branch(&cons_string, eq, at, Operand(zero_reg));
   1023 
   1024   // Handle slices.
   1025   Label indirect_string_loaded;
   1026   __ lw(result, FieldMemOperand(string, SlicedString::kOffsetOffset));
   1027   __ lw(string, FieldMemOperand(string, SlicedString::kParentOffset));
   1028   __ sra(at, result, kSmiTagSize);
   1029   __ Addu(index, index, at);
   1030   __ jmp(&indirect_string_loaded);
   1031 
   1032   // Handle cons strings.
   1033   // Check whether the right hand side is the empty string (i.e. if
   1034   // this is really a flat string in a cons string). If that is not
   1035   // the case we would rather go to the runtime system now to flatten
   1036   // the string.
   1037   __ bind(&cons_string);
   1038   __ lw(result, FieldMemOperand(string, ConsString::kSecondOffset));
   1039   __ LoadRoot(at, Heap::kempty_stringRootIndex);
   1040   __ Branch(call_runtime, ne, result, Operand(at));
   1041   // Get the first of the two strings and load its instance type.
   1042   __ lw(string, FieldMemOperand(string, ConsString::kFirstOffset));
   1043 
   1044   __ bind(&indirect_string_loaded);
   1045   __ lw(result, FieldMemOperand(string, HeapObject::kMapOffset));
   1046   __ lbu(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
   1047 
   1048   // Distinguish sequential and external strings. Only these two string
   1049   // representations can reach here (slices and flat cons strings have been
   1050   // reduced to the underlying sequential or external string).
   1051   Label external_string, check_encoding;
   1052   __ bind(&check_sequential);
   1053   STATIC_ASSERT(kSeqStringTag == 0);
   1054   __ And(at, result, Operand(kStringRepresentationMask));
   1055   __ Branch(&external_string, ne, at, Operand(zero_reg));
   1056 
   1057   // Prepare sequential strings
   1058   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
   1059   __ Addu(string,
   1060           string,
   1061           SeqTwoByteString::kHeaderSize - kHeapObjectTag);
   1062   __ jmp(&check_encoding);
   1063 
   1064   // Handle external strings.
   1065   __ bind(&external_string);
   1066   if (FLAG_debug_code) {
   1067     // Assert that we do not have a cons or slice (indirect strings) here.
   1068     // Sequential strings have already been ruled out.
   1069     __ And(at, result, Operand(kIsIndirectStringMask));
   1070     __ Assert(eq, kExternalStringExpectedButNotFound,
   1071         at, Operand(zero_reg));
   1072   }
   1073   // Rule out short external strings.
   1074   STATIC_ASSERT(kShortExternalStringTag != 0);
   1075   __ And(at, result, Operand(kShortExternalStringMask));
   1076   __ Branch(call_runtime, ne, at, Operand(zero_reg));
   1077   __ lw(string, FieldMemOperand(string, ExternalString::kResourceDataOffset));
   1078 
   1079   Label one_byte, done;
   1080   __ bind(&check_encoding);
   1081   STATIC_ASSERT(kTwoByteStringTag == 0);
   1082   __ And(at, result, Operand(kStringEncodingMask));
   1083   __ Branch(&one_byte, ne, at, Operand(zero_reg));
   1084   // Two-byte string.
   1085   __ sll(at, index, 1);
   1086   __ Addu(at, string, at);
   1087   __ lhu(result, MemOperand(at));
   1088   __ jmp(&done);
   1089   __ bind(&one_byte);
   1090   // One_byte string.
   1091   __ Addu(at, string, index);
   1092   __ lbu(result, MemOperand(at));
   1093   __ bind(&done);
   1094 }
   1095 
   1096 
   1097 static MemOperand ExpConstant(int index, Register base) {
   1098   return MemOperand(base, index * kDoubleSize);
   1099 }
   1100 
   1101 
   1102 void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
   1103                                    DoubleRegister input,
   1104                                    DoubleRegister result,
   1105                                    DoubleRegister double_scratch1,
   1106                                    DoubleRegister double_scratch2,
   1107                                    Register temp1,
   1108                                    Register temp2,
   1109                                    Register temp3) {
   1110   DCHECK(!input.is(result));
   1111   DCHECK(!input.is(double_scratch1));
   1112   DCHECK(!input.is(double_scratch2));
   1113   DCHECK(!result.is(double_scratch1));
   1114   DCHECK(!result.is(double_scratch2));
   1115   DCHECK(!double_scratch1.is(double_scratch2));
   1116   DCHECK(!temp1.is(temp2));
   1117   DCHECK(!temp1.is(temp3));
   1118   DCHECK(!temp2.is(temp3));
   1119   DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
   1120   DCHECK(!masm->serializer_enabled());  // External references not serializable.
   1121 
   1122   Label zero, infinity, done;
   1123 
   1124   __ li(temp3, Operand(ExternalReference::math_exp_constants(0)));
   1125 
   1126   __ ldc1(double_scratch1, ExpConstant(0, temp3));
   1127   __ BranchF(&zero, NULL, ge, double_scratch1, input);
   1128 
   1129   __ ldc1(double_scratch2, ExpConstant(1, temp3));
   1130   __ BranchF(&infinity, NULL, ge, input, double_scratch2);
   1131 
   1132   __ ldc1(double_scratch1, ExpConstant(3, temp3));
   1133   __ ldc1(result, ExpConstant(4, temp3));
   1134   __ mul_d(double_scratch1, double_scratch1, input);
   1135   __ add_d(double_scratch1, double_scratch1, result);
   1136   __ FmoveLow(temp2, double_scratch1);
   1137   __ sub_d(double_scratch1, double_scratch1, result);
   1138   __ ldc1(result, ExpConstant(6, temp3));
   1139   __ ldc1(double_scratch2, ExpConstant(5, temp3));
   1140   __ mul_d(double_scratch1, double_scratch1, double_scratch2);
   1141   __ sub_d(double_scratch1, double_scratch1, input);
   1142   __ sub_d(result, result, double_scratch1);
   1143   __ mul_d(double_scratch2, double_scratch1, double_scratch1);
   1144   __ mul_d(result, result, double_scratch2);
   1145   __ ldc1(double_scratch2, ExpConstant(7, temp3));
   1146   __ mul_d(result, result, double_scratch2);
   1147   __ sub_d(result, result, double_scratch1);
   1148   // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
   1149   DCHECK(*reinterpret_cast<double*>
   1150          (ExternalReference::math_exp_constants(8).address()) == 1);
   1151   __ Move(double_scratch2, 1.);
   1152   __ add_d(result, result, double_scratch2);
   1153   __ srl(temp1, temp2, 11);
   1154   __ Ext(temp2, temp2, 0, 11);
   1155   __ Addu(temp1, temp1, Operand(0x3ff));
   1156 
   1157   // Must not call ExpConstant() after overwriting temp3!
   1158   __ li(temp3, Operand(ExternalReference::math_exp_log_table()));
   1159   __ sll(at, temp2, 3);
   1160   __ Addu(temp3, temp3, Operand(at));
   1161   __ lw(temp2, MemOperand(temp3, Register::kMantissaOffset));
   1162   __ lw(temp3, MemOperand(temp3, Register::kExponentOffset));
   1163   // The first word is loaded is the lower number register.
   1164   if (temp2.code() < temp3.code()) {
   1165     __ sll(at, temp1, 20);
   1166     __ Or(temp1, temp3, at);
   1167     __ Move(double_scratch1, temp2, temp1);
   1168   } else {
   1169     __ sll(at, temp1, 20);
   1170     __ Or(temp1, temp2, at);
   1171     __ Move(double_scratch1, temp3, temp1);
   1172   }
   1173   __ mul_d(result, result, double_scratch1);
   1174   __ BranchShort(&done);
   1175 
   1176   __ bind(&zero);
   1177   __ Move(result, kDoubleRegZero);
   1178   __ BranchShort(&done);
   1179 
   1180   __ bind(&infinity);
   1181   __ ldc1(result, ExpConstant(2, temp3));
   1182 
   1183   __ bind(&done);
   1184 }
   1185 
   1186 #ifdef DEBUG
   1187 // nop(CODE_AGE_MARKER_NOP)
   1188 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180;
   1189 #endif
   1190 
   1191 
   1192 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {
   1193   USE(isolate);
   1194   DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength);
   1195   // Since patcher is a large object, allocate it dynamically when needed,
   1196   // to avoid overloading the stack in stress conditions.
   1197   // DONT_FLUSH is used because the CodeAgingHelper is initialized early in
   1198   // the process, before MIPS simulator ICache is setup.
   1199   base::SmartPointer<CodePatcher> patcher(
   1200       new CodePatcher(isolate, young_sequence_.start(),
   1201                       young_sequence_.length() / Assembler::kInstrSize,
   1202                       CodePatcher::DONT_FLUSH));
   1203   PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length());
   1204   patcher->masm()->Push(ra, fp, cp, a1);
   1205   patcher->masm()->nop(Assembler::CODE_AGE_SEQUENCE_NOP);
   1206   patcher->masm()->Addu(
   1207       fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
   1208 }
   1209 
   1210 
   1211 #ifdef DEBUG
   1212 bool CodeAgingHelper::IsOld(byte* candidate) const {
   1213   return Memory::uint32_at(candidate) == kCodeAgePatchFirstInstruction;
   1214 }
   1215 #endif
   1216 
   1217 
   1218 bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
   1219   bool result = isolate->code_aging_helper()->IsYoung(sequence);
   1220   DCHECK(result || isolate->code_aging_helper()->IsOld(sequence));
   1221   return result;
   1222 }
   1223 
   1224 
   1225 void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
   1226                                MarkingParity* parity) {
   1227   if (IsYoungSequence(isolate, sequence)) {
   1228     *age = kNoAgeCodeAge;
   1229     *parity = NO_MARKING_PARITY;
   1230   } else {
   1231     Address target_address = Assembler::target_address_at(
   1232         sequence + Assembler::kInstrSize);
   1233     Code* stub = GetCodeFromTargetAddress(target_address);
   1234     GetCodeAgeAndParity(stub, age, parity);
   1235   }
   1236 }
   1237 
   1238 
   1239 void Code::PatchPlatformCodeAge(Isolate* isolate,
   1240                                 byte* sequence,
   1241                                 Code::Age age,
   1242                                 MarkingParity parity) {
   1243   uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
   1244   if (age == kNoAgeCodeAge) {
   1245     isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
   1246     Assembler::FlushICache(isolate, sequence, young_length);
   1247   } else {
   1248     Code* stub = GetCodeAgeStub(isolate, age, parity);
   1249     CodePatcher patcher(isolate, sequence,
   1250                         young_length / Assembler::kInstrSize);
   1251     // Mark this code sequence for FindPlatformCodeAgeSequence().
   1252     patcher.masm()->nop(Assembler::CODE_AGE_MARKER_NOP);
   1253     // Load the stub address to t9 and call it,
   1254     // GetCodeAgeAndParity() extracts the stub address from this instruction.
   1255     patcher.masm()->li(
   1256         t9,
   1257         Operand(reinterpret_cast<uint32_t>(stub->instruction_start())),
   1258         CONSTANT_SIZE);
   1259     patcher.masm()->nop();  // Prevent jalr to jal optimization.
   1260     patcher.masm()->jalr(t9, a0);
   1261     patcher.masm()->nop();  // Branch delay slot nop.
   1262     patcher.masm()->nop();  // Pad the empty space.
   1263   }
   1264 }
   1265 
   1266 
   1267 #undef __
   1268 
   1269 }  // namespace internal
   1270 }  // namespace v8
   1271 
   1272 #endif  // V8_TARGET_ARCH_MIPS
   1273