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