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