| 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 |