13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_MIPS
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/mips/simulator-mips.h"
123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 {
143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal {
153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ masm.
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR)
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbyte* fast_exp_mips_machine_code = NULL;
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble fast_exp_simulator(double x) {
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Simulator::current(Isolate::Current())->CallFP(
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fast_exp_mips_machine_code, x, 0);
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochUnaryMathFunction CreateExpFunction() {
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_fast_math) return &std::exp;
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t actual_size;
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* buffer =
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (buffer == NULL) return &std::exp;
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference::InitializeMathExpData();
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoubleRegister input = f12;
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoubleRegister result = f0;
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoubleRegister double_scratch1 = f4;
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoubleRegister double_scratch2 = f6;
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp1 = t0;
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp2 = t1;
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp3 = t2;
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ MovFromFloatParameter(input);
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(temp3, temp2, temp1);
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MathExpGenerator::EmitMathExp(
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        &masm, input, result, double_scratch1, double_scratch2,
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        temp1, temp2, temp3);
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(temp3, temp2, temp1);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ MovToFloatResult(result);
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ret();
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm.GetCode(&desc);
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!RelocInfo::RequiresRelocation(desc));
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuFeatures::FlushICache(buffer, actual_size);
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::OS::ProtectCode(buffer, actual_size);
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if !defined(USE_SIMULATOR)
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FUNCTION_CAST<UnaryMathFunction>(buffer);
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fast_exp_mips_machine_code = buffer;
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return &fast_exp_simulator;
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(V8_HOST_ARCH_MIPS)
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub) {
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR) || defined(_MIPS_ARCH_MIPS32R6) || \
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    defined(_MIPS_ARCH_MIPS32RX)
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return stub;
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t actual_size;
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* buffer =
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<byte*>(base::OS::Allocate(3 * KB, &actual_size, true));
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (buffer == NULL) return stub;
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This code assumes that cache lines are 32 bytes and if the cache line is
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // larger it will not work correctly.
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label lastb, unaligned, aligned, chkw,
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          loop16w, chk1w, wordCopy_loop, skip_pref, lastbloop,
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          leave, ua_chk16w, ua_loop16w, ua_skip_pref, ua_chkw,
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ua_chk1w, ua_wordCopy_loop, ua_smallCopy, ua_smallCopy_loop;
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The size of each prefetch.
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t pref_chunk = 32;
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The maximum size of a prefetch, it must not be less then pref_chunk.
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the real size of a prefetch is greater then max_pref_size and
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the kPrefHintPrepareForStore hint is used, the code will not work
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // correctly.
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t max_pref_size = 128;
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(pref_chunk < max_pref_size);
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // pref_limit is set based on the fact that we never use an offset
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // greater then 5 on a store pref and that a single pref can
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // never be larger then max_pref_size.
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t pref_limit = (5 * pref_chunk) + max_pref_size;
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t pref_hint_load = kPrefHintLoadStreamed;
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t pref_hint_store = kPrefHintPrepareForStore;
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t loadstore_chunk = 4;
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The initial prefetches may fetch bytes that are before the buffer being
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // copied. Start copies with an offset of 4 so avoid this situation when
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // using kPrefHintPrepareForStore.
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(pref_hint_store != kPrefHintPrepareForStore ||
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           pref_chunk * 4 >= max_pref_size);
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the size is less than 8, go to lastb. Regardless of size,
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // copy dst pointer to v0 for the retuen value.
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ slti(t2, a2, 2 * loadstore_chunk);
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bne(t2, zero_reg, &lastb);
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(v0, a0);  // In delay slot.
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If src and dst have different alignments, go to unaligned, if they
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // have the same alignment (but are not actually aligned) do a partial
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // load/store to make them aligned. If they are both already aligned
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // we can start copying at aligned.
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ xor_(t8, a1, a0);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andi(t8, t8, loadstore_chunk - 1);  // t8 is a0/a1 word-displacement.
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bne(t8, zero_reg, &unaligned);
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subu(a3, zero_reg, a0);  // In delay slot.
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andi(a3, a3, loadstore_chunk - 1);  // Copy a3 bytes to align a0/a1.
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ beq(a3, zero_reg, &aligned);  // Already aligned.
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subu(a2, a2, a3);  // In delay slot. a2 is the remining bytes count.
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t8, MemOperand(a1));
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(a1, a1, a3);
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ swr(t8, MemOperand(a0));
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(a0, a0, a3);
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t8, MemOperand(a1));
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(a1, a1, a3);
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ swl(t8, MemOperand(a0));
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(a0, a0, a3);
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Now dst/src are both aligned to (word) aligned addresses. Set a2 to
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // count how many bytes we have to copy after all the 64 byte chunks are
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // copied and a3 to the dst pointer after all the 64 byte chunks have been
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // copied. We will loop, incrementing a0 and a1 until a0 equals a3.
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&aligned);
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andi(t8, a2, 0x3f);
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ beq(a2, t8, &chkw);  // Less than 64?
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subu(a3, a2, t8);  // In delay slot.
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addu(a3, a0, a3);  // Now a3 is the final dst after loop.
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // When in the loop we prefetch with kPrefHintPrepareForStore hint,
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // in this case the a0+x should be past the "t0-32" address. This means:
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // for x=128 the last "safe" a0 address is "t0-160". Alternatively, for
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // x=64 the last "safe" a0 address is "t0-96". In the current version we
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // will use "pref hint, 128(a0)", so "t0-160" is the limit.
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (pref_hint_store == kPrefHintPrepareForStore) {
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(t0, a0, a2);  // t0 is the "past the end" address.
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Subu(t9, t0, pref_limit);  // t9 is the "last safe pref" address.
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 0 * pref_chunk));
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 1 * pref_chunk));
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 2 * pref_chunk));
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 3 * pref_chunk));
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (pref_hint_store != kPrefHintPrepareForStore) {
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 1 * pref_chunk));
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 2 * pref_chunk));
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 3 * pref_chunk));
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&loop16w);
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t0, MemOperand(a1));
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (pref_hint_store == kPrefHintPrepareForStore) {
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ sltu(v1, t9, a0);  // If a0 > t9, don't use next prefetch.
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(USE_DELAY_SLOT, &skip_pref, gt, v1, Operand(zero_reg));
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t1, MemOperand(a1, 1, loadstore_chunk));  // Maybe in delay slot.
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk));
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk));
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&skip_pref);
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t2, MemOperand(a1, 2, loadstore_chunk));
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t3, MemOperand(a1, 3, loadstore_chunk));
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t4, MemOperand(a1, 4, loadstore_chunk));
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t5, MemOperand(a1, 5, loadstore_chunk));
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t6, MemOperand(a1, 6, loadstore_chunk));
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t7, MemOperand(a1, 7, loadstore_chunk));
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 4 * pref_chunk));
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t0, MemOperand(a0));
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t1, MemOperand(a0, 1, loadstore_chunk));
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t2, MemOperand(a0, 2, loadstore_chunk));
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t3, MemOperand(a0, 3, loadstore_chunk));
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t4, MemOperand(a0, 4, loadstore_chunk));
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t5, MemOperand(a0, 5, loadstore_chunk));
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t6, MemOperand(a0, 6, loadstore_chunk));
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t7, MemOperand(a0, 7, loadstore_chunk));
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t0, MemOperand(a1, 8, loadstore_chunk));
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t1, MemOperand(a1, 9, loadstore_chunk));
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t2, MemOperand(a1, 10, loadstore_chunk));
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t3, MemOperand(a1, 11, loadstore_chunk));
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t4, MemOperand(a1, 12, loadstore_chunk));
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t5, MemOperand(a1, 13, loadstore_chunk));
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t6, MemOperand(a1, 14, loadstore_chunk));
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t7, MemOperand(a1, 15, loadstore_chunk));
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 5 * pref_chunk));
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t0, MemOperand(a0, 8, loadstore_chunk));
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t1, MemOperand(a0, 9, loadstore_chunk));
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t2, MemOperand(a0, 10, loadstore_chunk));
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t3, MemOperand(a0, 11, loadstore_chunk));
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t4, MemOperand(a0, 12, loadstore_chunk));
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t5, MemOperand(a0, 13, loadstore_chunk));
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t6, MemOperand(a0, 14, loadstore_chunk));
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t7, MemOperand(a0, 15, loadstore_chunk));
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a0, a0, 16 * loadstore_chunk);
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bne(a0, a3, &loop16w);
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a1, a1, 16 * loadstore_chunk);  // In delay slot.
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(a2, t8);
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Here we have src and dest word-aligned but less than 64-bytes to go.
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check for a 32 bytes chunk and copy if there is one. Otherwise jump
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // down to chk1w to handle the tail end of the copy.
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&chkw);
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 0 * pref_chunk));
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andi(t8, a2, 0x1f);
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ beq(a2, t8, &chk1w);  // Less than 32?
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ nop();  // In delay slot.
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t0, MemOperand(a1));
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t1, MemOperand(a1, 1, loadstore_chunk));
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t2, MemOperand(a1, 2, loadstore_chunk));
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t3, MemOperand(a1, 3, loadstore_chunk));
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t4, MemOperand(a1, 4, loadstore_chunk));
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t5, MemOperand(a1, 5, loadstore_chunk));
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t6, MemOperand(a1, 6, loadstore_chunk));
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t7, MemOperand(a1, 7, loadstore_chunk));
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a1, a1, 8 * loadstore_chunk);
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t0, MemOperand(a0));
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t1, MemOperand(a0, 1, loadstore_chunk));
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t2, MemOperand(a0, 2, loadstore_chunk));
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t3, MemOperand(a0, 3, loadstore_chunk));
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t4, MemOperand(a0, 4, loadstore_chunk));
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t5, MemOperand(a0, 5, loadstore_chunk));
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t6, MemOperand(a0, 6, loadstore_chunk));
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t7, MemOperand(a0, 7, loadstore_chunk));
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a0, a0, 8 * loadstore_chunk);
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Here we have less than 32 bytes to copy. Set up for a loop to copy
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // one word at a time. Set a2 to count how many bytes we have to copy
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // after all the word chunks are copied and a3 to the dst pointer after
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // all the word chunks have been copied. We will loop, incrementing a0
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // and a1 untill a0 equals a3.
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&chk1w);
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andi(a2, t8, loadstore_chunk - 1);
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ beq(a2, t8, &lastb);
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subu(a3, t8, a2);  // In delay slot.
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addu(a3, a0, a3);
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&wordCopy_loop);
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t3, MemOperand(a1));
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a0, a0, loadstore_chunk);
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a1, a1, loadstore_chunk);
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bne(a0, a3, &wordCopy_loop);
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t3, MemOperand(a0, -1, loadstore_chunk));  // In delay slot.
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&lastb);
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&leave, le, a2, Operand(zero_reg));
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addu(a3, a0, a2);
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&lastbloop);
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lb(v1, MemOperand(a1));
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a0, a0, 1);
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a1, a1, 1);
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bne(a0, a3, &lastbloop);
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sb(v1, MemOperand(a0, -1));  // In delay slot.
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&leave);
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jr(ra);
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ nop();
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Unaligned case. Only the dst gets aligned so we need to do partial
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // loads of the source followed by normal stores to the dst (once we
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // have aligned the destination).
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&unaligned);
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andi(a3, a3, loadstore_chunk - 1);  // Copy a3 bytes to align a0/a1.
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ beq(a3, zero_reg, &ua_chk16w);
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subu(a2, a2, a3);  // In delay slot.
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(v1, MemOperand(a1));
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(v1,
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(a1, a1, a3);
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ swr(v1, MemOperand(a0));
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(a0, a0, a3);
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(v1, MemOperand(a1));
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(v1,
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(a1, a1, a3);
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ swl(v1, MemOperand(a0));
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(a0, a0, a3);
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Now the dst (but not the source) is aligned. Set a2 to count how many
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // bytes we have to copy after all the 64 byte chunks are copied and a3 to
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the dst pointer after all the 64 byte chunks have been copied. We will
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // loop, incrementing a0 and a1 until a0 equals a3.
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&ua_chk16w);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andi(t8, a2, 0x3f);
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ beq(a2, t8, &ua_chkw);
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subu(a3, a2, t8);  // In delay slot.
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addu(a3, a0, a3);
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (pref_hint_store == kPrefHintPrepareForStore) {
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addu(t0, a0, a2);
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Subu(t9, t0, pref_limit);
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 0 * pref_chunk));
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 1 * pref_chunk));
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 2 * pref_chunk));
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (pref_hint_store != kPrefHintPrepareForStore) {
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 1 * pref_chunk));
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 2 * pref_chunk));
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 3 * pref_chunk));
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&ua_loop16w);
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 3 * pref_chunk));
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t0, MemOperand(a1));
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t1, MemOperand(a1, 1, loadstore_chunk));
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t2, MemOperand(a1, 2, loadstore_chunk));
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (pref_hint_store == kPrefHintPrepareForStore) {
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sltu(v1, t9, a0);
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg));
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t3, MemOperand(a1, 3, loadstore_chunk));  // Maybe in delay slot.
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk));
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk));
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&ua_skip_pref);
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t4, MemOperand(a1, 4, loadstore_chunk));
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t5, MemOperand(a1, 5, loadstore_chunk));
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t6, MemOperand(a1, 6, loadstore_chunk));
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t7, MemOperand(a1, 7, loadstore_chunk));
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t0,
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t1,
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t2,
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t3,
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t4,
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t5,
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t6,
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t7,
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t0, MemOperand(a1));
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t1, MemOperand(a1, 1, loadstore_chunk));
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t2, MemOperand(a1, 2, loadstore_chunk));
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (pref_hint_store == kPrefHintPrepareForStore) {
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sltu(v1, t9, a0);
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg));
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t3, MemOperand(a1, 3, loadstore_chunk));  // Maybe in delay slot.
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk));
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk));
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&ua_skip_pref);
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t4, MemOperand(a1, 4, loadstore_chunk));
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t5, MemOperand(a1, 5, loadstore_chunk));
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t6, MemOperand(a1, 6, loadstore_chunk));
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t7, MemOperand(a1, 7, loadstore_chunk));
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t0,
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t1,
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t2,
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t3,
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t4,
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t5,
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t6,
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t7,
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 4 * pref_chunk));
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t0, MemOperand(a0));
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t1, MemOperand(a0, 1, loadstore_chunk));
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t2, MemOperand(a0, 2, loadstore_chunk));
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t3, MemOperand(a0, 3, loadstore_chunk));
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t4, MemOperand(a0, 4, loadstore_chunk));
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t5, MemOperand(a0, 5, loadstore_chunk));
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t6, MemOperand(a0, 6, loadstore_chunk));
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t7, MemOperand(a0, 7, loadstore_chunk));
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t0, MemOperand(a1, 8, loadstore_chunk));
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t1, MemOperand(a1, 9, loadstore_chunk));
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t2, MemOperand(a1, 10, loadstore_chunk));
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t3, MemOperand(a1, 11, loadstore_chunk));
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t4, MemOperand(a1, 12, loadstore_chunk));
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t5, MemOperand(a1, 13, loadstore_chunk));
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t6, MemOperand(a1, 14, loadstore_chunk));
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t7, MemOperand(a1, 15, loadstore_chunk));
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t0,
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one));
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t1,
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one));
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t2,
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one));
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t3,
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one));
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t4,
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one));
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t5,
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one));
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t6,
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one));
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t7,
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one));
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t0, MemOperand(a1, 8, loadstore_chunk));
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t1, MemOperand(a1, 9, loadstore_chunk));
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t2, MemOperand(a1, 10, loadstore_chunk));
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t3, MemOperand(a1, 11, loadstore_chunk));
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t4, MemOperand(a1, 12, loadstore_chunk));
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t5, MemOperand(a1, 13, loadstore_chunk));
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t6, MemOperand(a1, 14, loadstore_chunk));
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t7, MemOperand(a1, 15, loadstore_chunk));
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t0,
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one));
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t1,
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one));
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t2,
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one));
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t3,
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one));
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t4,
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one));
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t5,
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one));
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t6,
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one));
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t7,
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one));
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1, 5 * pref_chunk));
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t0, MemOperand(a0, 8, loadstore_chunk));
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t1, MemOperand(a0, 9, loadstore_chunk));
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t2, MemOperand(a0, 10, loadstore_chunk));
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t3, MemOperand(a0, 11, loadstore_chunk));
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t4, MemOperand(a0, 12, loadstore_chunk));
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t5, MemOperand(a0, 13, loadstore_chunk));
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t6, MemOperand(a0, 14, loadstore_chunk));
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t7, MemOperand(a0, 15, loadstore_chunk));
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a0, a0, 16 * loadstore_chunk);
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bne(a0, a3, &ua_loop16w);
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a1, a1, 16 * loadstore_chunk);  // In delay slot.
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(a2, t8);
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Here less than 64-bytes. Check for
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // a 32 byte chunk and copy if there is one. Otherwise jump down to
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // ua_chk1w to handle the tail end of the copy.
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&ua_chkw);
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pref(pref_hint_load, MemOperand(a1));
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andi(t8, a2, 0x1f);
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ beq(a2, t8, &ua_chk1w);
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ nop();  // In delay slot.
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t0, MemOperand(a1));
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t1, MemOperand(a1, 1, loadstore_chunk));
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t2, MemOperand(a1, 2, loadstore_chunk));
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t3, MemOperand(a1, 3, loadstore_chunk));
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t4, MemOperand(a1, 4, loadstore_chunk));
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t5, MemOperand(a1, 5, loadstore_chunk));
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t6, MemOperand(a1, 6, loadstore_chunk));
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t7, MemOperand(a1, 7, loadstore_chunk));
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t0,
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t1,
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t2,
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t3,
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t4,
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t5,
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t6,
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t7,
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t0, MemOperand(a1));
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t1, MemOperand(a1, 1, loadstore_chunk));
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t2, MemOperand(a1, 2, loadstore_chunk));
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t3, MemOperand(a1, 3, loadstore_chunk));
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t4, MemOperand(a1, 4, loadstore_chunk));
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t5, MemOperand(a1, 5, loadstore_chunk));
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t6, MemOperand(a1, 6, loadstore_chunk));
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(t7, MemOperand(a1, 7, loadstore_chunk));
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t0,
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t1,
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one));
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t2,
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one));
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t3,
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one));
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t4,
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one));
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t5,
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one));
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t6,
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one));
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(t7,
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one));
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a1, a1, 8 * loadstore_chunk);
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t0, MemOperand(a0));
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t1, MemOperand(a0, 1, loadstore_chunk));
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t2, MemOperand(a0, 2, loadstore_chunk));
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t3, MemOperand(a0, 3, loadstore_chunk));
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t4, MemOperand(a0, 4, loadstore_chunk));
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t5, MemOperand(a0, 5, loadstore_chunk));
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t6, MemOperand(a0, 6, loadstore_chunk));
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(t7, MemOperand(a0, 7, loadstore_chunk));
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a0, a0, 8 * loadstore_chunk);
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Less than 32 bytes to copy. Set up for a loop to
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // copy one word at a time.
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&ua_chk1w);
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andi(a2, t8, loadstore_chunk - 1);
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ beq(a2, t8, &ua_smallCopy);
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subu(a3, t8, a2);  // In delay slot.
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addu(a3, a0, a3);
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&ua_wordCopy_loop);
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kArchEndian == kLittle) {
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(v1, MemOperand(a1));
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(v1,
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwl(v1, MemOperand(a1));
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwr(v1,
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one));
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a0, a0, loadstore_chunk);
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a1, a1, loadstore_chunk);
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bne(a0, a3, &ua_wordCopy_loop);
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(v1, MemOperand(a0, -1, loadstore_chunk));  // In delay slot.
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Copy the last 8 bytes.
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&ua_smallCopy);
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ beq(a2, zero_reg, &leave);
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addu(a3, a0, a2);  // In delay slot.
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&ua_smallCopy_loop);
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lb(v1, MemOperand(a1));
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a0, a0, 1);
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addiu(a1, a1, 1);
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bne(a0, a3, &ua_smallCopy_loop);
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sb(v1, MemOperand(a0, -1));  // In delay slot.
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jr(ra);
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ nop();
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm.GetCode(&desc);
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!RelocInfo::RequiresRelocation(desc));
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuFeatures::FlushICache(buffer, actual_size);
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::OS::ProtectCode(buffer, actual_size);
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FUNCTION_CAST<MemCopyUint8Function>(buffer);
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUnaryMathFunction CreateSqrtFunction() {
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR)
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return &std::sqrt;
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t actual_size;
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* buffer =
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (buffer == NULL) return &std::sqrt;
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ MovFromFloatParameter(f12);
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sqrt_d(f0, f12);
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ MovToFloatResult(f0);
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret();
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm.GetCode(&desc);
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!RelocInfo::RequiresRelocation(desc));
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuFeatures::FlushICache(buffer, actual_size);
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::OS::ProtectCode(buffer, actual_size);
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FUNCTION_CAST<UnaryMathFunction>(buffer);
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
63644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// -------------------------------------------------------------------------
63744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Platform-specific RuntimeCallHelper functions.
63844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
63944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->EnterFrame(StackFrame::INTERNAL);
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!masm->has_frame());
6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->set_has_frame(true);
64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
64644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->LeaveFrame(StackFrame::INTERNAL);
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm->has_frame());
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->set_has_frame(false);
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// -------------------------------------------------------------------------
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Code generators
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm)
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm,
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver,
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register key,
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register target_map,
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSiteMode mode,
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* allocation_memento_found) {
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch_elements = t0;
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(receiver, key, value, target_map,
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     scratch_elements));
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == TRACK_ALLOCATION_SITE) {
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(allocation_memento_found != NULL);
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfJSArrayHasAllocationMemento(
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        receiver, scratch_elements, allocation_memento_found);
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set transitioned map.
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      target_map,
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      t5,
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kRAHasNotBeenSaved,
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      EMIT_REMEMBERED_SET,
6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementsTransitionGenerator::GenerateSmiToDouble(
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm,
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver,
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register key,
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register target_map,
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSiteMode mode,
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* fail) {
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Register ra contains the return address.
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry, convert_hole, gc_required, only_change_map, done;
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = t0;
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register length = t1;
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register array = t2;
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register array_end = array;
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // target_map parameter can be clobbered.
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch1 = target_map;
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = t5;
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch3 = t3;
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify input registers don't conflict with locals.
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(receiver, key, value, target_map,
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     elements, length, array, scratch2));
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = t6;
7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == TRACK_ALLOCATION_SITE) {
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for empty arrays, which only require a map transition and no changes
7203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to the backing store.
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&only_change_map, eq, at, Operand(elements));
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(ra);
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(length, FieldMemOperand(elements, FixedArray::kLengthOffset));
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // elements: source FixedArray
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // length: number of elements (smi-tagged)
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate new FixedDoubleArray.
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sll(scratch, length, 2);
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(scratch, scratch, FixedDoubleArray::kHeaderSize);
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(scratch, array, t3, scratch2, &gc_required, DOUBLE_ALIGNMENT);
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array: destination FixedDoubleArray, not tagged as heap object
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set destination FixedDoubleArray's length and map.
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(scratch2, Heap::kFixedDoubleArrayMapRootIndex);
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update receiver's map.
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(scratch2, MemOperand(array, HeapObject::kMapOffset));
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      target_map,
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch2,
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kRAHasBeenSaved,
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_REMEMBERED_SET,
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Replace receiver's backing store with newly created FixedDoubleArray.
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(scratch1, array, Operand(kHeapObjectTag));
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(scratch1, FieldMemOperand(a2, JSObject::kElementsOffset));
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      JSObject::kElementsOffset,
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch1,
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch2,
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kRAHasBeenSaved,
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      EMIT_REMEMBERED_SET,
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Prepare for conversion loop.
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(scratch1, elements,
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand(FixedArray::kHeaderSize - kHeapObjectTag));
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(scratch3, array, Operand(FixedDoubleArray::kHeaderSize));
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sll(at, length, 2);
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(array_end, scratch3, at);
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Repurpose registers no longer in use.
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register hole_lower = elements;
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register hole_upper = length;
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(hole_lower, Operand(kHoleNanLower32));
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch1: begin of source FixedArray element fields, not tagged
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hole_lower: kHoleNanLower32
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hole_upper: kHoleNanUpper32
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array_end: end of destination FixedDoubleArray, not tagged
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch3: begin of FixedDoubleArray element fields, not tagged
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(USE_DELAY_SLOT, &entry);
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(hole_upper, Operand(kHoleNanUpper32));  // In delay slot.
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&only_change_map);
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      target_map,
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch2,
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kRAHasBeenSaved,
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_REMEMBERED_SET,
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done);
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call into runtime if GC is required.
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&gc_required);
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(ra, MemOperand(sp, 0));
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(USE_DELAY_SLOT, fail);
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addiu(sp, sp, kPointerSize);  // In delay slot.
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Convert and copy elements.
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&loop);
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(scratch2, MemOperand(scratch1));
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(scratch1, scratch1, kIntSize);
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch2: current element
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ UntagAndJumpIfNotSmi(scratch2, scratch2, &convert_hole);
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Normal smi, convert to double and store.
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mtc1(scratch2, f0);
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cvt_d_w(f0, f0);
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sdc1(f0, MemOperand(scratch3));
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(USE_DELAY_SLOT, &entry);
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addiu(scratch3, scratch3, kDoubleSize);  // In delay slot.
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Hole found, store the-hole NaN.
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&convert_hole);
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore a "smi-untagged" heap object.
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTag(scratch2);
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Or(scratch2, scratch2, Operand(1));
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(eq, kObjectFoundInSmiOnlyArray, at, Operand(scratch2));
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // mantissa
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(hole_lower, MemOperand(scratch3, Register::kMantissaOffset));
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // exponent
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(hole_upper, MemOperand(scratch3, Register::kExponentOffset));
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&entry);
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addiu(scratch3, scratch3, kDoubleSize);
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&loop, lt, scratch3, Operand(array_end));
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(ra);
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ElementsTransitionGenerator::GenerateDoubleToObject(
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm,
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver,
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register key,
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register target_map,
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSiteMode mode,
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* fail) {
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Register ra contains the return address.
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label entry, loop, convert_hole, gc_required, only_change_map;
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = t0;
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register array = t2;
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register length = t1;
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = t5;
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify input registers don't conflict with locals.
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(receiver, key, value, target_map,
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     elements, array, length, scratch));
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == TRACK_ALLOCATION_SITE) {
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for empty arrays, which only require a map transition and no changes
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to the backing store.
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&only_change_map, eq, at, Operand(elements));
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ MultiPush(
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      value.bit() | key.bit() | receiver.bit() | target_map.bit() | ra.bit());
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(length, FieldMemOperand(elements, FixedArray::kLengthOffset));
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // elements: source FixedArray
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // length: number of elements (smi-tagged)
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate new FixedArray.
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Re-use value and target_map registers, as they have been saved on the
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stack.
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register array_size = value;
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register allocate_scratch = target_map;
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sll(array_size, length, 1);
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(array_size, array_size, FixedDoubleArray::kHeaderSize);
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required,
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              NO_ALLOCATION_FLAGS);
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array: destination FixedArray, not tagged as heap object
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set destination FixedDoubleArray's length and map.
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(scratch, MemOperand(array, HeapObject::kMapOffset));
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Prepare for conversion loop.
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register src_elements = elements;
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dst_elements = target_map;
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dst_end = length;
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register heap_number_map = scratch;
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(src_elements, src_elements, Operand(
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FixedDoubleArray::kHeaderSize - kHeapObjectTag
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        + Register::kExponentOffset));
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(dst_elements, array, Operand(FixedArray::kHeaderSize));
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(array, array, Operand(kHeapObjectTag));
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sll(dst_end, dst_end, 1);
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(dst_end, dst_elements, dst_end);
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Using offsetted addresses.
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // dst_elements: begin of destination FixedArray element fields, not tagged
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // src_elements: begin of source FixedDoubleArray element fields, not tagged,
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //               points to the exponent
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // dst_end: end of destination FixedArray, not tagged
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array: destination FixedArray
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // heap_number_map: heap number map
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&entry);
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call into runtime if GC is required.
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&gc_required);
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ MultiPop(
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      value.bit() | key.bit() | receiver.bit() | target_map.bit() | ra.bit());
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(fail);
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&loop);
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register upper_bits = key;
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(upper_bits, MemOperand(src_elements));
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(src_elements, src_elements, kDoubleSize);
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // upper_bits: current element's upper 32 bit
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // src_elements: address of next element's upper 32 bit
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&convert_hole, eq, a1, Operand(kHoleNanUpper32));
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Non-hole double, copy value into a heap number.
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register heap_number = receiver;
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = value;
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch3 = t6;
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AllocateHeapNumber(heap_number, scratch2, scratch3, heap_number_map,
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        &gc_required);
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // heap_number: new heap number
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load mantissa of current element, src_elements
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // point to exponent of next element.
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(scratch2, MemOperand(src_elements, (Register::kMantissaOffset
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      - Register::kExponentOffset - kDoubleSize)));
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(scratch2, FieldMemOperand(heap_number, HeapNumber::kMantissaOffset));
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(upper_bits, FieldMemOperand(heap_number, HeapNumber::kExponentOffset));
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(scratch2, dst_elements);
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(heap_number, MemOperand(dst_elements));
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(dst_elements, dst_elements, kIntSize);
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWrite(array,
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 scratch2,
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 heap_number,
9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 kRAHasBeenSaved,
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 kDontSaveFPRegs,
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 EMIT_REMEMBERED_SET,
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 OMIT_SMI_CHECK);
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&entry);
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Replace the-hole NaN with the-hole pointer.
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&convert_hole);
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(scratch2, Heap::kTheHoleValueRootIndex);
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(scratch2, MemOperand(dst_elements));
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(dst_elements, dst_elements, kIntSize);
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&entry);
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&loop, lt, dst_elements, Operand(dst_end));
9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ MultiPop(receiver.bit() | target_map.bit() | value.bit() | key.bit());
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Replace receiver's backing store with newly created and filled FixedArray.
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(array, FieldMemOperand(receiver, JSObject::kElementsOffset));
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      JSObject::kElementsOffset,
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      array,
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch,
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kRAHasBeenSaved,
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      EMIT_REMEMBERED_SET,
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(ra);
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&only_change_map);
9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update receiver's map.
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      target_map,
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch,
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kRAHasNotBeenSaved,
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_REMEMBERED_SET,
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StringCharLoadGenerator::Generate(MacroAssembler* masm,
9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register string,
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register index,
9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register result,
9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* call_runtime) {
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fetch the instance type of the receiver into result register.
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(string, HeapObject::kMapOffset));
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lbu(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We need special handling for indirect strings.
9983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_sequential;
9993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, result, Operand(kIsIndirectStringMask));
10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&check_sequential, eq, at, Operand(zero_reg));
10013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Dispatch on the indirect string shape: slice or cons.
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label cons_string;
10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, result, Operand(kSlicedNotConsMask));
10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&cons_string, eq, at, Operand(zero_reg));
10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle slices.
10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label indirect_string_loaded;
10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(string, SlicedString::kOffsetOffset));
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(string, FieldMemOperand(string, SlicedString::kParentOffset));
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sra(at, result, kSmiTagSize);
10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(index, index, at);
10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&indirect_string_loaded);
10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle cons strings.
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check whether the right hand side is the empty string (i.e. if
10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // this is really a flat string in a cons string). If that is not
10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the case we would rather go to the runtime system now to flatten
10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the string.
10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&cons_string);
10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(string, ConsString::kSecondOffset));
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(at, Heap::kempty_stringRootIndex);
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(call_runtime, ne, result, Operand(at));
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the first of the two strings and load its instance type.
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(string, FieldMemOperand(string, ConsString::kFirstOffset));
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&indirect_string_loaded);
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(string, HeapObject::kMapOffset));
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lbu(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Distinguish sequential and external strings. Only these two string
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // representations can reach here (slices and flat cons strings have been
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // reduced to the underlying sequential or external string).
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label external_string, check_encoding;
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&check_sequential);
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kSeqStringTag == 0);
10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, result, Operand(kStringRepresentationMask));
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&external_string, ne, at, Operand(zero_reg));
10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Prepare sequential strings
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(string,
10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          string,
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          SeqTwoByteString::kHeaderSize - kHeapObjectTag);
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&check_encoding);
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle external strings.
10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&external_string);
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Assert that we do not have a cons or slice (indirect strings) here.
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Sequential strings have already been ruled out.
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(at, result, Operand(kIsIndirectStringMask));
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(eq, kExternalStringExpectedButNotFound,
10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        at, Operand(zero_reg));
10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Rule out short external strings.
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kShortExternalStringTag != 0);
10583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, result, Operand(kShortExternalStringMask));
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(call_runtime, ne, at, Operand(zero_reg));
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(string, FieldMemOperand(string, ExternalString::kResourceDataOffset));
10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label one_byte, done;
10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&check_encoding);
10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kTwoByteStringTag == 0);
10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, result, Operand(kStringEncodingMask));
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&one_byte, ne, at, Operand(zero_reg));
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Two-byte string.
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(at, index, 1);
10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(at, string, at);
10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lhu(result, MemOperand(at));
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&one_byte);
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // One_byte string.
10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(at, string, index);
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lbu(result, MemOperand(at));
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
10773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic MemOperand ExpConstant(int index, Register base) {
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return MemOperand(base, index * kDoubleSize);
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MathExpGenerator::EmitMathExp(MacroAssembler* masm,
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   DoubleRegister input,
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   DoubleRegister result,
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   DoubleRegister double_scratch1,
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   DoubleRegister double_scratch2,
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register temp1,
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register temp2,
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register temp3) {
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(result));
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(double_scratch1));
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(double_scratch2));
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(double_scratch1));
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(double_scratch2));
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!double_scratch1.is(double_scratch2));
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp1.is(temp2));
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp1.is(temp3));
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp2.is(temp3));
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!masm->serializer_enabled());  // External references not serializable.
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label zero, infinity, done;
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(temp3, Operand(ExternalReference::math_exp_constants(0)));
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldc1(double_scratch1, ExpConstant(0, temp3));
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ BranchF(&zero, NULL, ge, double_scratch1, input);
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldc1(double_scratch2, ExpConstant(1, temp3));
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ BranchF(&infinity, NULL, ge, input, double_scratch2);
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldc1(double_scratch1, ExpConstant(3, temp3));
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldc1(result, ExpConstant(4, temp3));
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mul_d(double_scratch1, double_scratch1, input);
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add_d(double_scratch1, double_scratch1, result);
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ FmoveLow(temp2, double_scratch1);
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub_d(double_scratch1, double_scratch1, result);
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldc1(result, ExpConstant(6, temp3));
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldc1(double_scratch2, ExpConstant(5, temp3));
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mul_d(double_scratch1, double_scratch1, double_scratch2);
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub_d(double_scratch1, double_scratch1, input);
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub_d(result, result, double_scratch1);
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mul_d(double_scratch2, double_scratch1, double_scratch1);
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mul_d(result, result, double_scratch2);
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldc1(double_scratch2, ExpConstant(7, temp3));
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mul_d(result, result, double_scratch2);
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub_d(result, result, double_scratch1);
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(*reinterpret_cast<double*>
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (ExternalReference::math_exp_constants(8).address()) == 1);
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(double_scratch2, 1);
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add_d(result, result, double_scratch2);
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ srl(temp1, temp2, 11);
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ext(temp2, temp2, 0, 11);
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(temp1, temp1, Operand(0x3ff));
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Must not call ExpConstant() after overwriting temp3!
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(temp3, Operand(ExternalReference::math_exp_log_table()));
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sll(at, temp2, 3);
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(temp3, temp3, Operand(at));
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(temp2, MemOperand(temp3, Register::kMantissaOffset));
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(temp3, MemOperand(temp3, Register::kExponentOffset));
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The first word is loaded is the lower number register.
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (temp2.code() < temp3.code()) {
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sll(at, temp1, 20);
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Or(temp1, temp3, at);
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(double_scratch1, temp2, temp1);
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sll(at, temp1, 20);
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Or(temp1, temp2, at);
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(double_scratch1, temp3, temp1);
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mul_d(result, result, double_scratch1);
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ BranchShort(&done);
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&zero);
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(result, kDoubleRegZero);
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ BranchShort(&done);
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&infinity);
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldc1(result, ExpConstant(2, temp3));
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// nop(CODE_AGE_MARKER_NOP)
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const uint32_t kCodeAgePatchFirstInstruction = 0x00010180;
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCodeAgingHelper::CodeAgingHelper() {
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength);
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Since patcher is a large object, allocate it dynamically when needed,
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to avoid overloading the stack in stress conditions.
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // DONT_FLUSH is used because the CodeAgingHelper is initialized early in
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the process, before MIPS simulator ICache is setup.
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmartPointer<CodePatcher> patcher(
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new CodePatcher(young_sequence_.start(),
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      young_sequence_.length() / Assembler::kInstrSize,
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      CodePatcher::DONT_FLUSH));
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length());
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patcher->masm()->Push(ra, fp, cp, a1);
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patcher->masm()->nop(Assembler::CODE_AGE_SEQUENCE_NOP);
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patcher->masm()->Addu(
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CodeAgingHelper::IsOld(byte* candidate) const {
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Memory::uint32_at(candidate) == kCodeAgePatchFirstInstruction;
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool result = isolate->code_aging_helper()->IsYoung(sequence);
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result || isolate->code_aging_helper()->IsOld(sequence));
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               MarkingParity* parity) {
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsYoungSequence(isolate, sequence)) {
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *age = kNoAgeCodeAge;
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *parity = NO_MARKING_PARITY;
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address target_address = Assembler::target_address_at(
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sequence + Assembler::kInstrSize);
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* stub = GetCodeFromTargetAddress(target_address);
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GetCodeAgeAndParity(stub, age, parity);
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Code::PatchPlatformCodeAge(Isolate* isolate,
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                byte* sequence,
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Code::Age age,
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                MarkingParity parity) {
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (age == kNoAgeCodeAge) {
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatures::FlushICache(sequence, young_length);
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* stub = GetCodeAgeStub(isolate, age, parity);
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodePatcher patcher(sequence, young_length / Assembler::kInstrSize);
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Mark this code sequence for FindPlatformCodeAgeSequence().
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->nop(Assembler::CODE_AGE_MARKER_NOP);
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the stub address to t9 and call it,
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // GetCodeAgeAndParity() extracts the stub address from this instruction.
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->li(
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        t9,
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand(reinterpret_cast<uint32_t>(stub->instruction_start())),
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CONSTANT_SIZE);
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->nop();  // Prevent jalr to jal optimization.
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->jalr(t9, a0);
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->nop();  // Branch delay slot nop.
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->nop();  // Pad the empty space.
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef __
12493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} }  // namespace v8::internal
1251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_MIPS
1253