Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Side by Side Diff: runtime/vm/intrinsifier_mips.cc

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/intrinsifier_ia32.cc ('k') | runtime/vm/intrinsifier_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/intrinsifier.h" 8 #include "vm/intrinsifier.h"
9 9
10 #include "vm/assembler.h" 10 #include "vm/assembler.h"
(...skipping 11 matching lines...) Expand all
22 // S4: Arguments descriptor 22 // S4: Arguments descriptor
23 // RA: Return address 23 // RA: Return address
24 // The S4 register can be destroyed only if there is no slow-path, i.e. 24 // The S4 register can be destroyed only if there is no slow-path, i.e.
25 // if the intrinsified method always executes a return. 25 // if the intrinsified method always executes a return.
26 // The FP register should not be modified, because it is used by the profiler. 26 // The FP register should not be modified, because it is used by the profiler.
27 // The PP and THR registers (see constants_mips.h) must be preserved. 27 // The PP and THR registers (see constants_mips.h) must be preserved.
28 28
29 #define __ assembler-> 29 #define __ assembler->
30 30
31 31
32 intptr_t Intrinsifier::ParameterSlotFromSp() { return -1; } 32 intptr_t Intrinsifier::ParameterSlotFromSp() {
33 return -1;
34 }
33 35
34 36
35 static bool IsABIPreservedRegister(Register reg) { 37 static bool IsABIPreservedRegister(Register reg) {
36 return ((1 << reg) & kAbiPreservedCpuRegs) != 0; 38 return ((1 << reg) & kAbiPreservedCpuRegs) != 0;
37 } 39 }
38 40
39 void Intrinsifier::IntrinsicCallPrologue(Assembler* assembler) { 41 void Intrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
40 ASSERT(IsABIPreservedRegister(CODE_REG)); 42 ASSERT(IsABIPreservedRegister(CODE_REG));
41 ASSERT(IsABIPreservedRegister(ARGS_DESC_REG)); 43 ASSERT(IsABIPreservedRegister(ARGS_DESC_REG));
42 ASSERT(IsABIPreservedRegister(CALLEE_SAVED_TEMP)); 44 ASSERT(IsABIPreservedRegister(CALLEE_SAVED_TEMP));
(...skipping 26 matching lines...) Expand all
69 71
70 __ lw(T0, Address(SP, 2 * kWordSize)); // Array. 72 __ lw(T0, Address(SP, 2 * kWordSize)); // Array.
71 // Range check. 73 // Range check.
72 __ lw(T3, FieldAddress(T0, Array::length_offset())); // Array length. 74 __ lw(T3, FieldAddress(T0, Array::length_offset())); // Array length.
73 // Runtime throws exception. 75 // Runtime throws exception.
74 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); 76 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through);
75 77
76 // Note that T1 is Smi, i.e, times 2. 78 // Note that T1 is Smi, i.e, times 2.
77 ASSERT(kSmiTagShift == 1); 79 ASSERT(kSmiTagShift == 1);
78 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. 80 __ lw(T2, Address(SP, 0 * kWordSize)); // Value.
79 __ sll(T1, T1, 1); // T1 is Smi. 81 __ sll(T1, T1, 1); // T1 is Smi.
80 __ addu(T1, T0, T1); 82 __ addu(T1, T0, T1);
81 __ StoreIntoObject(T0, 83 __ StoreIntoObject(T0, FieldAddress(T1, Array::data_offset()), T2);
82 FieldAddress(T1, Array::data_offset()),
83 T2);
84 // Caller is responsible for preserving the value if necessary. 84 // Caller is responsible for preserving the value if necessary.
85 __ Ret(); 85 __ Ret();
86 __ Bind(&fall_through); 86 __ Bind(&fall_through);
87 } 87 }
88 88
89 89
90 // Allocate a GrowableObjectArray using the backing array specified. 90 // Allocate a GrowableObjectArray using the backing array specified.
91 // On stack: type argument (+1), data (+0). 91 // On stack: type argument (+1), data (+0).
92 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { 92 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) {
93 // The newly allocated object is returned in V0. 93 // The newly allocated object is returned in V0.
94 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; 94 const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
95 const intptr_t kArrayOffset = 0 * kWordSize; 95 const intptr_t kArrayOffset = 0 * kWordSize;
96 Label fall_through; 96 Label fall_through;
97 97
98 // Try allocating in new space. 98 // Try allocating in new space.
99 const Class& cls = Class::Handle( 99 const Class& cls = Class::Handle(
100 Isolate::Current()->object_store()->growable_object_array_class()); 100 Isolate::Current()->object_store()->growable_object_array_class());
101 __ TryAllocate(cls, &fall_through, V0, T1); 101 __ TryAllocate(cls, &fall_through, V0, T1);
102 102
103 // Store backing array object in growable array object. 103 // Store backing array object in growable array object.
104 __ lw(T1, Address(SP, kArrayOffset)); // Data argument. 104 __ lw(T1, Address(SP, kArrayOffset)); // Data argument.
105 // V0 is new, no barrier needed. 105 // V0 is new, no barrier needed.
106 __ StoreIntoObjectNoBarrier( 106 __ StoreIntoObjectNoBarrier(
107 V0, 107 V0, FieldAddress(V0, GrowableObjectArray::data_offset()), T1);
108 FieldAddress(V0, GrowableObjectArray::data_offset()),
109 T1);
110 108
111 // V0: new growable array object start as a tagged pointer. 109 // V0: new growable array object start as a tagged pointer.
112 // Store the type argument field in the growable array object. 110 // Store the type argument field in the growable array object.
113 __ lw(T1, Address(SP, kTypeArgumentsOffset)); // Type argument. 111 __ lw(T1, Address(SP, kTypeArgumentsOffset)); // Type argument.
114 __ StoreIntoObjectNoBarrier( 112 __ StoreIntoObjectNoBarrier(
115 V0, 113 V0, FieldAddress(V0, GrowableObjectArray::type_arguments_offset()), T1);
116 FieldAddress(V0, GrowableObjectArray::type_arguments_offset()),
117 T1);
118 // Set the length field in the growable array object to 0. 114 // Set the length field in the growable array object to 0.
119 __ Ret(); // Returns the newly allocated object in V0. 115 __ Ret(); // Returns the newly allocated object in V0.
120 __ delay_slot()->sw(ZR, 116 __ delay_slot()->sw(ZR,
121 FieldAddress(V0, GrowableObjectArray::length_offset())); 117 FieldAddress(V0, GrowableObjectArray::length_offset()));
122 118
123 __ Bind(&fall_through); 119 __ Bind(&fall_through);
124 } 120 }
125 121
126 122
127 // Add an element to growable array if it doesn't need to grow, otherwise 123 // Add an element to growable array if it doesn't need to grow, otherwise
128 // call into regular code. 124 // call into regular code.
129 // On stack: growable array (+1), value (+0). 125 // On stack: growable array (+1), value (+0).
130 void Intrinsifier::GrowableArray_add(Assembler* assembler) { 126 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
131 // In checked mode we need to type-check the incoming argument. 127 // In checked mode we need to type-check the incoming argument.
132 if (Isolate::Current()->type_checks()) return; 128 if (Isolate::Current()->type_checks()) return;
133 Label fall_through; 129 Label fall_through;
134 __ lw(T0, Address(SP, 1 * kWordSize)); // Array. 130 __ lw(T0, Address(SP, 1 * kWordSize)); // Array.
135 __ lw(T1, FieldAddress(T0, GrowableObjectArray::length_offset())); 131 __ lw(T1, FieldAddress(T0, GrowableObjectArray::length_offset()));
136 // T1: length. 132 // T1: length.
137 __ lw(T2, FieldAddress(T0, GrowableObjectArray::data_offset())); 133 __ lw(T2, FieldAddress(T0, GrowableObjectArray::data_offset()));
138 // T2: data. 134 // T2: data.
139 __ lw(T3, FieldAddress(T2, Array::length_offset())); 135 __ lw(T3, FieldAddress(T2, Array::length_offset()));
140 // Compare length with capacity. 136 // Compare length with capacity.
141 // T3: capacity. 137 // T3: capacity.
142 __ beq(T1, T3, &fall_through); // Must grow data. 138 __ beq(T1, T3, &fall_through); // Must grow data.
143 const int32_t value_one = reinterpret_cast<int32_t>(Smi::New(1)); 139 const int32_t value_one = reinterpret_cast<int32_t>(Smi::New(1));
144 // len = len + 1; 140 // len = len + 1;
145 __ addiu(T3, T1, Immediate(value_one)); 141 __ addiu(T3, T1, Immediate(value_one));
146 __ sw(T3, FieldAddress(T0, GrowableObjectArray::length_offset())); 142 __ sw(T3, FieldAddress(T0, GrowableObjectArray::length_offset()));
147 __ lw(T0, Address(SP, 0 * kWordSize)); // Value. 143 __ lw(T0, Address(SP, 0 * kWordSize)); // Value.
148 ASSERT(kSmiTagShift == 1); 144 ASSERT(kSmiTagShift == 1);
149 __ sll(T1, T1, 1); 145 __ sll(T1, T1, 1);
150 __ addu(T1, T2, T1); 146 __ addu(T1, T2, T1);
151 __ StoreIntoObject(T2, 147 __ StoreIntoObject(T2, FieldAddress(T1, Array::data_offset()), T0);
152 FieldAddress(T1, Array::data_offset()),
153 T0);
154 __ LoadObject(T7, Object::null_object()); 148 __ LoadObject(T7, Object::null_object());
155 __ Ret(); 149 __ Ret();
156 __ delay_slot()->mov(V0, T7); 150 __ delay_slot()->mov(V0, T7);
157 __ Bind(&fall_through); 151 __ Bind(&fall_through);
158 } 152 }
159 153
160 154
161 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \ 155 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \
162 Label fall_through; \ 156 Label fall_through; \
163 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \ 157 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \
164 NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, T2, &fall_through)); \ 158 NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, T2, &fall_through)); \
165 __ lw(T2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \ 159 __ lw(T2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \
166 /* Check that length is a positive Smi. */ \ 160 /* Check that length is a positive Smi. */ \
167 /* T2: requested array length argument. */ \ 161 /* T2: requested array length argument. */ \
168 __ andi(CMPRES1, T2, Immediate(kSmiTagMask)); \ 162 __ andi(CMPRES1, T2, Immediate(kSmiTagMask)); \
169 __ bne(CMPRES1, ZR, &fall_through); \ 163 __ bne(CMPRES1, ZR, &fall_through); \
170 __ BranchSignedLess(T2, Immediate(0), &fall_through); \ 164 __ BranchSignedLess(T2, Immediate(0), &fall_through); \
171 __ SmiUntag(T2); \ 165 __ SmiUntag(T2); \
172 /* Check for maximum allowed length. */ \ 166 /* Check for maximum allowed length. */ \
173 /* T2: untagged array length. */ \ 167 /* T2: untagged array length. */ \
174 __ BranchSignedGreater(T2, Immediate(max_len), &fall_through); \ 168 __ BranchSignedGreater(T2, Immediate(max_len), &fall_through); \
175 __ sll(T2, T2, scale_shift); \ 169 __ sll(T2, T2, scale_shift); \
(...skipping 26 matching lines...) Expand all
202 /* Initialize the tags. */ \ 196 /* Initialize the tags. */ \
203 /* V0: new object start as a tagged pointer. */ \ 197 /* V0: new object start as a tagged pointer. */ \
204 /* T1: new object end address. */ \ 198 /* T1: new object end address. */ \
205 /* T2: allocation size. */ \ 199 /* T2: allocation size. */ \
206 { \ 200 { \
207 Label size_tag_overflow, done; \ 201 Label size_tag_overflow, done; \
208 __ BranchUnsignedGreater(T2, Immediate(RawObject::SizeTag::kMaxSizeTag), \ 202 __ BranchUnsignedGreater(T2, Immediate(RawObject::SizeTag::kMaxSizeTag), \
209 &size_tag_overflow); \ 203 &size_tag_overflow); \
210 __ b(&done); \ 204 __ b(&done); \
211 __ delay_slot()->sll(T2, T2, \ 205 __ delay_slot()->sll(T2, T2, \
212 RawObject::kSizeTagPos - kObjectAlignmentLog2); \ 206 RawObject::kSizeTagPos - kObjectAlignmentLog2); \
213 \ 207 \
214 __ Bind(&size_tag_overflow); \ 208 __ Bind(&size_tag_overflow); \
215 __ mov(T2, ZR); \ 209 __ mov(T2, ZR); \
216 __ Bind(&done); \ 210 __ Bind(&done); \
217 \ 211 \
218 /* Get the class index and insert it into the tags. */ \ 212 /* Get the class index and insert it into the tags. */ \
219 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); \ 213 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); \
220 __ or_(T2, T2, TMP); \ 214 __ or_(T2, T2, TMP); \
221 __ sw(T2, FieldAddress(V0, type_name::tags_offset())); /* Tags. */ \ 215 __ sw(T2, FieldAddress(V0, type_name::tags_offset())); /* Tags. */ \
222 } \ 216 } \
223 /* Set the length field. */ \ 217 /* Set the length field. */ \
224 /* V0: new object start as a tagged pointer. */ \ 218 /* V0: new object start as a tagged pointer. */ \
225 /* T1: new object end address. */ \ 219 /* T1: new object end address. */ \
226 __ lw(T2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \ 220 __ lw(T2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \
227 __ StoreIntoObjectNoBarrier(V0, \ 221 __ StoreIntoObjectNoBarrier( \
228 FieldAddress(V0, type_name::length_offset()), \ 222 V0, FieldAddress(V0, type_name::length_offset()), T2); \
229 T2); \
230 /* Initialize all array elements to 0. */ \ 223 /* Initialize all array elements to 0. */ \
231 /* V0: new object start as a tagged pointer. */ \ 224 /* V0: new object start as a tagged pointer. */ \
232 /* T1: new object end address. */ \ 225 /* T1: new object end address. */ \
233 /* T2: iterator which initially points to the start of the variable */ \ 226 /* T2: iterator which initially points to the start of the variable */ \
234 /* data area to be initialized. */ \ 227 /* data area to be initialized. */ \
235 __ AddImmediate(T2, V0, sizeof(Raw##type_name) - 1); \ 228 __ AddImmediate(T2, V0, sizeof(Raw##type_name) - 1); \
236 Label done, init_loop; \ 229 Label done, init_loop; \
237 __ Bind(&init_loop); \ 230 __ Bind(&init_loop); \
238 __ BranchUnsignedGreaterEqual(T2, T1, &done); \ 231 __ BranchUnsignedGreaterEqual(T2, T1, &done); \
239 __ sw(ZR, Address(T2, 0)); \ 232 __ sw(ZR, Address(T2, 0)); \
240 __ b(&init_loop); \ 233 __ b(&init_loop); \
241 __ delay_slot()->addiu(T2, T2, Immediate(kWordSize)); \ 234 __ delay_slot()->addiu(T2, T2, Immediate(kWordSize)); \
242 __ Bind(&done); \ 235 __ Bind(&done); \
243 \ 236 \
244 __ Ret(); \ 237 __ Ret(); \
245 __ Bind(&fall_through); \ 238 __ Bind(&fall_through);
246 239
247 240
248 static int GetScaleFactor(intptr_t size) { 241 static int GetScaleFactor(intptr_t size) {
249 switch (size) { 242 switch (size) {
250 case 1: return 0; 243 case 1:
251 case 2: return 1; 244 return 0;
252 case 4: return 2; 245 case 2:
253 case 8: return 3; 246 return 1;
254 case 16: return 4; 247 case 4:
248 return 2;
249 case 8:
250 return 3;
251 case 16:
252 return 4;
255 } 253 }
256 UNREACHABLE(); 254 UNREACHABLE();
257 return -1; 255 return -1;
258 } 256 }
259 257
260 258
261 #define TYPED_DATA_ALLOCATOR(clazz) \ 259 #define TYPED_DATA_ALLOCATOR(clazz) \
262 void Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler) { \ 260 void Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler) { \
263 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \ 261 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \
264 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \ 262 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \
265 int shift = GetScaleFactor(size); \ 263 int shift = GetScaleFactor(size); \
266 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, shift); \ 264 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, shift); \
267 } 265 }
268 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR) 266 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
269 #undef TYPED_DATA_ALLOCATOR 267 #undef TYPED_DATA_ALLOCATOR
270 268
271 269
272 // Loads args from stack into T0 and T1 270 // Loads args from stack into T0 and T1
273 // Tests if they are smis, jumps to label not_smi if not. 271 // Tests if they are smis, jumps to label not_smi if not.
274 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { 272 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
275 __ lw(T0, Address(SP, 0 * kWordSize)); 273 __ lw(T0, Address(SP, 0 * kWordSize));
276 __ lw(T1, Address(SP, 1 * kWordSize)); 274 __ lw(T1, Address(SP, 1 * kWordSize));
277 __ or_(CMPRES1, T0, T1); 275 __ or_(CMPRES1, T0, T1);
278 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask)); 276 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask));
279 __ bne(CMPRES1, ZR, not_smi); 277 __ bne(CMPRES1, ZR, not_smi);
280 return; 278 return;
281 } 279 }
282 280
283 281
284 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) { 282 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
285 Label fall_through; 283 Label fall_through;
286 284
287 TestBothArgumentsSmis(assembler, &fall_through); // Checks two Smis. 285 TestBothArgumentsSmis(assembler, &fall_through); // Checks two Smis.
288 __ AdduDetectOverflow(V0, T0, T1, CMPRES1); // Add. 286 __ AdduDetectOverflow(V0, T0, T1, CMPRES1); // Add.
289 __ bltz(CMPRES1, &fall_through); // Fall through on overflow. 287 __ bltz(CMPRES1, &fall_through); // Fall through on overflow.
290 __ Ret(); // Nothing in branch delay slot. 288 __ Ret(); // Nothing in branch delay slot.
291 __ Bind(&fall_through); 289 __ Bind(&fall_through);
292 } 290 }
293 291
294 292
295 void Intrinsifier::Integer_add(Assembler* assembler) { 293 void Intrinsifier::Integer_add(Assembler* assembler) {
296 Integer_addFromInteger(assembler); 294 Integer_addFromInteger(assembler);
297 } 295 }
298 296
299 297
300 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) { 298 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
301 Label fall_through; 299 Label fall_through;
302 300
303 TestBothArgumentsSmis(assembler, &fall_through); 301 TestBothArgumentsSmis(assembler, &fall_through);
304 __ SubuDetectOverflow(V0, T0, T1, CMPRES1); // Subtract. 302 __ SubuDetectOverflow(V0, T0, T1, CMPRES1); // Subtract.
305 __ bltz(CMPRES1, &fall_through); // Fall through on overflow. 303 __ bltz(CMPRES1, &fall_through); // Fall through on overflow.
306 __ Ret(); 304 __ Ret();
307 __ Bind(&fall_through); 305 __ Bind(&fall_through);
308 } 306 }
309 307
310 308
311 void Intrinsifier::Integer_sub(Assembler* assembler) { 309 void Intrinsifier::Integer_sub(Assembler* assembler) {
312 Label fall_through; 310 Label fall_through;
313 311
314 TestBothArgumentsSmis(assembler, &fall_through); 312 TestBothArgumentsSmis(assembler, &fall_through);
315 __ SubuDetectOverflow(V0, T1, T0, CMPRES1); // Subtract. 313 __ SubuDetectOverflow(V0, T1, T0, CMPRES1); // Subtract.
316 __ bltz(CMPRES1, &fall_through); // Fall through on overflow. 314 __ bltz(CMPRES1, &fall_through); // Fall through on overflow.
317 __ Ret(); // Nothing in branch delay slot. 315 __ Ret(); // Nothing in branch delay slot.
318 __ Bind(&fall_through); 316 __ Bind(&fall_through);
319 } 317 }
320 318
321 319
322 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { 320 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
323 Label fall_through; 321 Label fall_through;
324 322
325 TestBothArgumentsSmis(assembler, &fall_through); // checks two smis 323 TestBothArgumentsSmis(assembler, &fall_through); // checks two smis
326 __ SmiUntag(T0); // untags T0. only want result shifted by one 324 __ SmiUntag(T0); // untags T0. only want result shifted by one
327 325
328 __ mult(T0, T1); // HI:LO <- T0 * T1. 326 __ mult(T0, T1); // HI:LO <- T0 * T1.
329 __ mflo(V0); // V0 <- LO. 327 __ mflo(V0); // V0 <- LO.
330 __ mfhi(T2); // T2 <- HI. 328 __ mfhi(T2); // T2 <- HI.
331 __ sra(T3, V0, 31); // T3 <- V0 >> 31. 329 __ sra(T3, V0, 31); // T3 <- V0 >> 31.
332 __ bne(T2, T3, &fall_through); // Fall through on overflow. 330 __ bne(T2, T3, &fall_through); // Fall through on overflow.
333 __ Ret(); 331 __ Ret();
334 __ Bind(&fall_through); 332 __ Bind(&fall_through);
335 } 333 }
336 334
337 335
338 void Intrinsifier::Integer_mul(Assembler* assembler) { 336 void Intrinsifier::Integer_mul(Assembler* assembler) {
339 Integer_mulFromInteger(assembler); 337 Integer_mulFromInteger(assembler);
340 } 338 }
341 339
(...skipping 26 matching lines...) Expand all
368 __ delay_slot()->mov(result, left); 366 __ delay_slot()->mov(result, left);
369 367
370 __ Bind(&return_zero); 368 __ Bind(&return_zero);
371 __ Ret(); 369 __ Ret();
372 __ delay_slot()->mov(result, ZR); 370 __ delay_slot()->mov(result, ZR);
373 371
374 __ Bind(&modulo); 372 __ Bind(&modulo);
375 __ SmiUntag(right); 373 __ SmiUntag(right);
376 __ SmiUntag(left); 374 __ SmiUntag(left);
377 __ div(left, right); // Divide, remainder goes in HI. 375 __ div(left, right); // Divide, remainder goes in HI.
378 __ mfhi(result); // result <- HI. 376 __ mfhi(result); // result <- HI.
379 return; 377 return;
380 } 378 }
381 379
382 380
383 // Implementation: 381 // Implementation:
384 // res = left % right; 382 // res = left % right;
385 // if (res < 0) { 383 // if (res < 0) {
386 // if (right < 0) { 384 // if (right < 0) {
387 // res = res - right; 385 // res = res - right;
388 // } else { 386 // } else {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 424
427 void Intrinsifier::Integer_truncDivide(Assembler* assembler) { 425 void Intrinsifier::Integer_truncDivide(Assembler* assembler) {
428 Label fall_through; 426 Label fall_through;
429 427
430 TestBothArgumentsSmis(assembler, &fall_through); 428 TestBothArgumentsSmis(assembler, &fall_through);
431 __ beq(T0, ZR, &fall_through); // If b is 0, fall through. 429 __ beq(T0, ZR, &fall_through); // If b is 0, fall through.
432 430
433 __ SmiUntag(T0); 431 __ SmiUntag(T0);
434 __ SmiUntag(T1); 432 __ SmiUntag(T1);
435 __ div(T1, T0); // LO <- T1 / T0 433 __ div(T1, T0); // LO <- T1 / T0
436 __ mflo(V0); // V0 <- LO 434 __ mflo(V0); // V0 <- LO
437 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we 435 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
438 // cannot tag the result. 436 // cannot tag the result.
439 __ BranchEqual(V0, Immediate(0x40000000), &fall_through); 437 __ BranchEqual(V0, Immediate(0x40000000), &fall_through);
440 __ Ret(); 438 __ Ret();
441 __ delay_slot()->SmiTag(V0); 439 __ delay_slot()->SmiTag(V0);
442 __ Bind(&fall_through); 440 __ Bind(&fall_through);
443 } 441 }
444 442
445 443
446 void Intrinsifier::Integer_negate(Assembler* assembler) { 444 void Intrinsifier::Integer_negate(Assembler* assembler) {
447 Label fall_through; 445 Label fall_through;
448 446
449 __ lw(T0, Address(SP, + 0 * kWordSize)); // Grabs first argument. 447 __ lw(T0, Address(SP, +0 * kWordSize)); // Grabs first argument.
450 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); // Test for Smi. 448 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); // Test for Smi.
451 __ bne(CMPRES1, ZR, &fall_through); // Fall through if not a Smi. 449 __ bne(CMPRES1, ZR, &fall_through); // Fall through if not a Smi.
452 __ SubuDetectOverflow(V0, ZR, T0, CMPRES1); 450 __ SubuDetectOverflow(V0, ZR, T0, CMPRES1);
453 __ bltz(CMPRES1, &fall_through); // There was overflow. 451 __ bltz(CMPRES1, &fall_through); // There was overflow.
454 __ Ret(); 452 __ Ret();
455 __ Bind(&fall_through); 453 __ Bind(&fall_through);
456 } 454 }
457 455
458 456
459 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) { 457 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
460 Label fall_through; 458 Label fall_through;
461 459
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 Integer_bitXorFromInteger(assembler); 498 Integer_bitXorFromInteger(assembler);
501 } 499 }
502 500
503 501
504 void Intrinsifier::Integer_shl(Assembler* assembler) { 502 void Intrinsifier::Integer_shl(Assembler* assembler) {
505 ASSERT(kSmiTagShift == 1); 503 ASSERT(kSmiTagShift == 1);
506 ASSERT(kSmiTag == 0); 504 ASSERT(kSmiTag == 0);
507 Label fall_through, overflow; 505 Label fall_through, overflow;
508 506
509 TestBothArgumentsSmis(assembler, &fall_through); 507 TestBothArgumentsSmis(assembler, &fall_through);
510 __ BranchUnsignedGreater( 508 __ BranchUnsignedGreater(T0, Immediate(Smi::RawValue(Smi::kBits)),
511 T0, Immediate(Smi::RawValue(Smi::kBits)), &fall_through); 509 &fall_through);
512 __ SmiUntag(T0); 510 __ SmiUntag(T0);
513 511
514 // Check for overflow by shifting left and shifting back arithmetically. 512 // Check for overflow by shifting left and shifting back arithmetically.
515 // If the result is different from the original, there was overflow. 513 // If the result is different from the original, there was overflow.
516 __ sllv(TMP, T1, T0); 514 __ sllv(TMP, T1, T0);
517 __ srav(CMPRES1, TMP, T0); 515 __ srav(CMPRES1, TMP, T0);
518 __ bne(CMPRES1, T1, &overflow); 516 __ bne(CMPRES1, T1, &overflow);
519 517
520 // No overflow, result in V0. 518 // No overflow, result in V0.
521 __ Ret(); 519 __ Ret();
522 __ delay_slot()->sllv(V0, T1, T0); 520 __ delay_slot()->sllv(V0, T1, T0);
523 521
524 __ Bind(&overflow); 522 __ Bind(&overflow);
525 // Arguments are Smi but the shift produced an overflow to Mint. 523 // Arguments are Smi but the shift produced an overflow to Mint.
526 __ bltz(T1, &fall_through); 524 __ bltz(T1, &fall_through);
527 __ SmiUntag(T1); 525 __ SmiUntag(T1);
528 526
529 // Pull off high bits that will be shifted off of T1 by making a mask 527 // Pull off high bits that will be shifted off of T1 by making a mask
530 // ((1 << T0) - 1), shifting it to the right, masking T1, then shifting back. 528 // ((1 << T0) - 1), shifting it to the right, masking T1, then shifting back.
531 // high bits = (((1 << T0) - 1) << (32 - T0)) & T1) >> (32 - T0) 529 // high bits = (((1 << T0) - 1) << (32 - T0)) & T1) >> (32 - T0)
532 // lo bits = T1 << T0 530 // lo bits = T1 << T0
533 __ LoadImmediate(T3, 1); 531 __ LoadImmediate(T3, 1);
534 __ sllv(T3, T3, T0); // T3 <- T3 << T0 532 __ sllv(T3, T3, T0); // T3 <- T3 << T0
535 __ addiu(T3, T3, Immediate(-1)); // T3 <- T3 - 1 533 __ addiu(T3, T3, Immediate(-1)); // T3 <- T3 - 1
536 __ subu(T4, ZR, T0); // T4 <- -T0 534 __ subu(T4, ZR, T0); // T4 <- -T0
537 __ addiu(T4, T4, Immediate(32)); // T4 <- 32 - T0 535 __ addiu(T4, T4, Immediate(32)); // T4 <- 32 - T0
538 __ sllv(T3, T3, T4); // T3 <- T3 << T4 536 __ sllv(T3, T3, T4); // T3 <- T3 << T4
539 __ and_(T3, T3, T1); // T3 <- T3 & T1 537 __ and_(T3, T3, T1); // T3 <- T3 & T1
540 __ srlv(T3, T3, T4); // T3 <- T3 >> T4 538 __ srlv(T3, T3, T4); // T3 <- T3 >> T4
541 // Now T3 has the bits that fall off of T1 on a left shift. 539 // Now T3 has the bits that fall off of T1 on a left shift.
542 __ sllv(T0, T1, T0); // T0 gets low bits. 540 __ sllv(T0, T1, T0); // T0 gets low bits.
543 541
544 const Class& mint_class = Class::Handle( 542 const Class& mint_class =
545 Isolate::Current()->object_store()->mint_class()); 543 Class::Handle(Isolate::Current()->object_store()->mint_class());
546 __ TryAllocate(mint_class, &fall_through, V0, T1); 544 __ TryAllocate(mint_class, &fall_through, V0, T1);
547 545
548 __ sw(T0, FieldAddress(V0, Mint::value_offset())); 546 __ sw(T0, FieldAddress(V0, Mint::value_offset()));
549 __ Ret(); 547 __ Ret();
550 __ delay_slot()->sw(T3, FieldAddress(V0, Mint::value_offset() + kWordSize)); 548 __ delay_slot()->sw(T3, FieldAddress(V0, Mint::value_offset() + kWordSize));
551 __ Bind(&fall_through); 549 __ Bind(&fall_through);
552 } 550 }
553 551
554 552
555 static void Get64SmiOrMint(Assembler* assembler, 553 static void Get64SmiOrMint(Assembler* assembler,
(...skipping 22 matching lines...) Expand all
578 return; 576 return;
579 } 577 }
580 578
581 579
582 static void CompareIntegers(Assembler* assembler, RelationOperator rel_op) { 580 static void CompareIntegers(Assembler* assembler, RelationOperator rel_op) {
583 Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through; 581 Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through;
584 TestBothArgumentsSmis(assembler, &try_mint_smi); 582 TestBothArgumentsSmis(assembler, &try_mint_smi);
585 // T0 contains the right argument. T1 contains left argument 583 // T0 contains the right argument. T1 contains left argument
586 584
587 switch (rel_op) { 585 switch (rel_op) {
588 case LT: __ BranchSignedLess(T1, T0, &is_true); break; 586 case LT:
589 case LE: __ BranchSignedLessEqual(T1, T0, &is_true); break; 587 __ BranchSignedLess(T1, T0, &is_true);
590 case GT: __ BranchSignedGreater(T1, T0, &is_true); break; 588 break;
591 case GE: __ BranchSignedGreaterEqual(T1, T0, &is_true); break; 589 case LE:
590 __ BranchSignedLessEqual(T1, T0, &is_true);
591 break;
592 case GT:
593 __ BranchSignedGreater(T1, T0, &is_true);
594 break;
595 case GE:
596 __ BranchSignedGreaterEqual(T1, T0, &is_true);
597 break;
592 default: 598 default:
593 UNREACHABLE(); 599 UNREACHABLE();
594 break; 600 break;
595 } 601 }
596 602
597 __ Bind(&is_false); 603 __ Bind(&is_false);
598 __ LoadObject(V0, Bool::False()); 604 __ LoadObject(V0, Bool::False());
599 __ Ret(); 605 __ Ret();
600 __ Bind(&is_true); 606 __ Bind(&is_true);
601 __ LoadObject(V0, Bool::True()); 607 __ LoadObject(V0, Bool::True());
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 void Intrinsifier::Integer_sar(Assembler* assembler) { 742 void Intrinsifier::Integer_sar(Assembler* assembler) {
737 Label fall_through; 743 Label fall_through;
738 744
739 TestBothArgumentsSmis(assembler, &fall_through); 745 TestBothArgumentsSmis(assembler, &fall_through);
740 // Shift amount in T0. Value to shift in T1. 746 // Shift amount in T0. Value to shift in T1.
741 747
742 __ SmiUntag(T0); 748 __ SmiUntag(T0);
743 __ bltz(T0, &fall_through); 749 __ bltz(T0, &fall_through);
744 750
745 __ LoadImmediate(T2, 0x1F); 751 __ LoadImmediate(T2, 0x1F);
746 __ slt(CMPRES1, T2, T0); // CMPRES1 <- 0x1F < T0 ? 1 : 0 752 __ slt(CMPRES1, T2, T0); // CMPRES1 <- 0x1F < T0 ? 1 : 0
747 __ movn(T0, T2, CMPRES1); // T0 <- 0x1F < T0 ? 0x1F : T0 753 __ movn(T0, T2, CMPRES1); // T0 <- 0x1F < T0 ? 0x1F : T0
748 754
749 __ SmiUntag(T1); 755 __ SmiUntag(T1);
750 __ srav(V0, T1, T0); 756 __ srav(V0, T1, T0);
751 __ Ret(); 757 __ Ret();
752 __ delay_slot()->SmiTag(V0); 758 __ delay_slot()->SmiTag(V0);
753 __ Bind(&fall_through); 759 __ Bind(&fall_through);
754 } 760 }
755 761
756 762
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 __ addiu(T4, T3, Immediate(TypedData::data_offset() - kHeapObjectTag)); 1177 __ addiu(T4, T3, Immediate(TypedData::data_offset() - kHeapObjectTag));
1172 1178
1173 // T3 = x = *xip++, return if x == 0 1179 // T3 = x = *xip++, return if x == 0
1174 Label x_zero; 1180 Label x_zero;
1175 __ lw(T3, Address(T4, 0)); 1181 __ lw(T3, Address(T4, 0));
1176 __ beq(T3, ZR, &x_zero); 1182 __ beq(T3, ZR, &x_zero);
1177 __ delay_slot()->addiu(T4, T4, Immediate(Bigint::kBytesPerDigit)); 1183 __ delay_slot()->addiu(T4, T4, Immediate(Bigint::kBytesPerDigit));
1178 1184
1179 // T5 = ajp = &a_digits[i] 1185 // T5 = ajp = &a_digits[i]
1180 __ lw(T1, Address(SP, 1 * kWordSize)); // a_digits 1186 __ lw(T1, Address(SP, 1 * kWordSize)); // a_digits
1181 __ sll(T0, T2, 2); // j == 2*i, i is Smi. 1187 __ sll(T0, T2, 2); // j == 2*i, i is Smi.
1182 __ addu(T1, T0, T1); 1188 __ addu(T1, T0, T1);
1183 __ addiu(T5, T1, Immediate(TypedData::data_offset() - kHeapObjectTag)); 1189 __ addiu(T5, T1, Immediate(TypedData::data_offset() - kHeapObjectTag));
1184 1190
1185 // T6:T0 = t = x*x + *ajp 1191 // T6:T0 = t = x*x + *ajp
1186 __ lw(T0, Address(T5, 0)); // *ajp. 1192 __ lw(T0, Address(T5, 0)); // *ajp.
1187 __ mthi(ZR); 1193 __ mthi(ZR);
1188 __ mtlo(T0); 1194 __ mtlo(T0);
1189 __ maddu(T3, T3); // HI:LO = T3*T3 + *ajp. 1195 __ maddu(T3, T3); // HI:LO = T3*T3 + *ajp.
1190 __ mfhi(T6); 1196 __ mfhi(T6);
1191 __ mflo(T0); 1197 __ mflo(T0);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1232 __ srl(T1, A0, 31); 1238 __ srl(T1, A0, 31);
1233 __ or_(A1, A1, T1); 1239 __ or_(A1, A1, T1);
1234 __ sll(A0, A0, 1); // A2:A1:A0 = 2*x*xi. 1240 __ sll(A0, A0, 1); // A2:A1:A0 = 2*x*xi.
1235 __ addu(A0, A0, T0); 1241 __ addu(A0, A0, T0);
1236 __ sltu(T1, A0, T0); 1242 __ sltu(T1, A0, T0);
1237 __ addu(A1, A1, T1); // No carry out possible; A2:A1:A0 = 2*x*xi + aj. 1243 __ addu(A1, A1, T1); // No carry out possible; A2:A1:A0 = 2*x*xi + aj.
1238 __ addu(T0, A0, T6); 1244 __ addu(T0, A0, T6);
1239 __ sltu(T1, T0, T6); 1245 __ sltu(T1, T0, T6);
1240 __ addu(T6, A1, T1); // No carry out; A2:T6:T0 = 2*x*xi + aj + low32(c). 1246 __ addu(T6, A1, T1); // No carry out; A2:T6:T0 = 2*x*xi + aj + low32(c).
1241 __ addu(T6, T6, T7); // No carry out; A2:T6:T0 = 2*x*xi + aj + c. 1247 __ addu(T6, T6, T7); // No carry out; A2:T6:T0 = 2*x*xi + aj + c.
1242 __ mov(T7, A2); // T7:T6:T0 = 2*x*xi + aj + c. 1248 __ mov(T7, A2); // T7:T6:T0 = 2*x*xi + aj + c.
1243 1249
1244 // *ajp++ = low32(t) = T0 1250 // *ajp++ = low32(t) = T0
1245 __ sw(T0, Address(T5, 0)); 1251 __ sw(T0, Address(T5, 0));
1246 __ addiu(T5, T5, Immediate(Bigint::kBytesPerDigit)); 1252 __ addiu(T5, T5, Immediate(Bigint::kBytesPerDigit));
1247 1253
1248 // while (n-- > 0) 1254 // while (n-- > 0)
1249 __ bgtz(V0, &loop); 1255 __ bgtz(V0, &loop);
1250 __ delay_slot()->addiu(V0, V0, Immediate(-1)); // --n 1256 __ delay_slot()->addiu(V0, V0, Immediate(-1)); // --n
1251 1257
1252 __ Bind(&done); 1258 __ Bind(&done);
(...skipping 28 matching lines...) Expand all
1281 // uint32_t d = digits[i >> 1]; // i is Smi. 1287 // uint32_t d = digits[i >> 1]; // i is Smi.
1282 // uint64_t t = rho*d; 1288 // uint64_t t = rho*d;
1283 // args[_MU] = t mod DIGIT_BASE; // _MU == 4. 1289 // args[_MU] = t mod DIGIT_BASE; // _MU == 4.
1284 // return 1; 1290 // return 1;
1285 // } 1291 // }
1286 1292
1287 // T4 = args 1293 // T4 = args
1288 __ lw(T4, Address(SP, 2 * kWordSize)); // args 1294 __ lw(T4, Address(SP, 2 * kWordSize)); // args
1289 1295
1290 // T3 = rho = args[2] 1296 // T3 = rho = args[2]
1291 __ lw(T3, 1297 __ lw(T3, FieldAddress(
1292 FieldAddress(T4, TypedData::data_offset() + 2*Bigint::kBytesPerDigit)); 1298 T4, TypedData::data_offset() + 2 * Bigint::kBytesPerDigit));
1293 1299
1294 // T2 = d = digits[i >> 1] 1300 // T2 = d = digits[i >> 1]
1295 __ lw(T0, Address(SP, 0 * kWordSize)); // T0 = i as Smi. 1301 __ lw(T0, Address(SP, 0 * kWordSize)); // T0 = i as Smi.
1296 __ lw(T1, Address(SP, 1 * kWordSize)); // T1 = digits. 1302 __ lw(T1, Address(SP, 1 * kWordSize)); // T1 = digits.
1297 __ sll(T0, T0, 1); 1303 __ sll(T0, T0, 1);
1298 __ addu(T1, T0, T1); 1304 __ addu(T1, T0, T1);
1299 __ lw(T2, FieldAddress(T1, TypedData::data_offset())); 1305 __ lw(T2, FieldAddress(T1, TypedData::data_offset()));
1300 1306
1301 // HI:LO = t = rho*d 1307 // HI:LO = t = rho*d
1302 __ multu(T2, T3); 1308 __ multu(T2, T3);
1303 1309
1304 // args[4] = t mod DIGIT_BASE = low32(t) 1310 // args[4] = t mod DIGIT_BASE = low32(t)
1305 __ mflo(T0); 1311 __ mflo(T0);
1306 __ sw(T0, 1312 __ sw(T0, FieldAddress(
1307 FieldAddress(T4, TypedData::data_offset() + 4*Bigint::kBytesPerDigit)); 1313 T4, TypedData::data_offset() + 4 * Bigint::kBytesPerDigit));
1308 1314
1309 __ addiu(V0, ZR, Immediate(Smi::RawValue(1))); // One digit processed. 1315 __ addiu(V0, ZR, Immediate(Smi::RawValue(1))); // One digit processed.
1310 __ Ret(); 1316 __ Ret();
1311 } 1317 }
1312 1318
1313 1319
1314 // Check if the last argument is a double, jump to label 'is_smi' if smi 1320 // Check if the last argument is a double, jump to label 'is_smi' if smi
1315 // (easy to convert to double), otherwise jump to label 'not_double_smi', 1321 // (easy to convert to double), otherwise jump to label 'not_double_smi',
1316 // Returns the last argument in T0. 1322 // Returns the last argument in T0.
1317 static void TestLastArgumentIsDouble(Assembler* assembler, 1323 static void TestLastArgumentIsDouble(Assembler* assembler,
(...skipping 24 matching lines...) Expand all
1342 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag); 1348 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag);
1343 // Now, left is in D0, right is in D1. 1349 // Now, left is in D0, right is in D1.
1344 1350
1345 __ cund(D0, D1); // Check for NaN. 1351 __ cund(D0, D1); // Check for NaN.
1346 __ bc1f(&no_NaN); 1352 __ bc1f(&no_NaN);
1347 __ LoadObject(V0, Bool::False()); // Return false if either is NaN. 1353 __ LoadObject(V0, Bool::False()); // Return false if either is NaN.
1348 __ Ret(); 1354 __ Ret();
1349 __ Bind(&no_NaN); 1355 __ Bind(&no_NaN);
1350 1356
1351 switch (rel_op) { 1357 switch (rel_op) {
1352 case EQ: __ ceqd(D0, D1); break; 1358 case EQ:
1353 case LT: __ coltd(D0, D1); break; 1359 __ ceqd(D0, D1);
1354 case LE: __ coled(D0, D1); break; 1360 break;
1355 case GT: __ coltd(D1, D0); break; 1361 case LT:
1356 case GE: __ coled(D1, D0); break; 1362 __ coltd(D0, D1);
1363 break;
1364 case LE:
1365 __ coled(D0, D1);
1366 break;
1367 case GT:
1368 __ coltd(D1, D0);
1369 break;
1370 case GE:
1371 __ coled(D1, D0);
1372 break;
1357 default: { 1373 default: {
1358 // Only passing the above conditions to this function. 1374 // Only passing the above conditions to this function.
1359 UNREACHABLE(); 1375 UNREACHABLE();
1360 break; 1376 break;
1361 } 1377 }
1362 } 1378 }
1363 1379
1364 Label is_true; 1380 Label is_true;
1365 __ bc1t(&is_true); 1381 __ bc1t(&is_true);
1366 __ LoadObject(V0, Bool::False()); 1382 __ LoadObject(V0, Bool::False());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1413 1429
1414 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1430 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1415 // Both arguments are double, right operand is in T0. 1431 // Both arguments are double, right operand is in T0.
1416 __ lwc1(F2, FieldAddress(T0, Double::value_offset())); 1432 __ lwc1(F2, FieldAddress(T0, Double::value_offset()));
1417 __ lwc1(F3, FieldAddress(T0, Double::value_offset() + kWordSize)); 1433 __ lwc1(F3, FieldAddress(T0, Double::value_offset() + kWordSize));
1418 __ Bind(&double_op); 1434 __ Bind(&double_op);
1419 __ lw(T0, Address(SP, 1 * kWordSize)); // Left argument. 1435 __ lw(T0, Address(SP, 1 * kWordSize)); // Left argument.
1420 __ lwc1(F0, FieldAddress(T0, Double::value_offset())); 1436 __ lwc1(F0, FieldAddress(T0, Double::value_offset()));
1421 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); 1437 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize));
1422 switch (kind) { 1438 switch (kind) {
1423 case Token::kADD: __ addd(D0, D0, D1); break; 1439 case Token::kADD:
1424 case Token::kSUB: __ subd(D0, D0, D1); break; 1440 __ addd(D0, D0, D1);
1425 case Token::kMUL: __ muld(D0, D0, D1); break; 1441 break;
1426 case Token::kDIV: __ divd(D0, D0, D1); break; 1442 case Token::kSUB:
1427 default: UNREACHABLE(); 1443 __ subd(D0, D0, D1);
1444 break;
1445 case Token::kMUL:
1446 __ muld(D0, D0, D1);
1447 break;
1448 case Token::kDIV:
1449 __ divd(D0, D0, D1);
1450 break;
1451 default:
1452 UNREACHABLE();
1428 } 1453 }
1429 const Class& double_class = Class::Handle( 1454 const Class& double_class =
1430 Isolate::Current()->object_store()->double_class()); 1455 Class::Handle(Isolate::Current()->object_store()->double_class());
1431 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. 1456 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register.
1432 __ swc1(F0, FieldAddress(V0, Double::value_offset())); 1457 __ swc1(F0, FieldAddress(V0, Double::value_offset()));
1433 __ Ret(); 1458 __ Ret();
1434 __ delay_slot()->swc1(F1, 1459 __ delay_slot()->swc1(F1,
1435 FieldAddress(V0, Double::value_offset() + kWordSize)); 1460 FieldAddress(V0, Double::value_offset() + kWordSize));
1436 1461
1437 __ Bind(&is_smi); 1462 __ Bind(&is_smi);
1438 __ SmiUntag(T0); 1463 __ SmiUntag(T0);
1439 __ mtc1(T0, STMP1); 1464 __ mtc1(T0, STMP1);
1440 __ b(&double_op); 1465 __ b(&double_op);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 1499
1475 // Is Smi. 1500 // Is Smi.
1476 __ SmiUntag(T0); 1501 __ SmiUntag(T0);
1477 __ mtc1(T0, F4); 1502 __ mtc1(T0, F4);
1478 __ cvtdw(D1, F4); 1503 __ cvtdw(D1, F4);
1479 1504
1480 __ lw(T0, Address(SP, 1 * kWordSize)); 1505 __ lw(T0, Address(SP, 1 * kWordSize));
1481 __ lwc1(F0, FieldAddress(T0, Double::value_offset())); 1506 __ lwc1(F0, FieldAddress(T0, Double::value_offset()));
1482 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); 1507 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize));
1483 __ muld(D0, D0, D1); 1508 __ muld(D0, D0, D1);
1484 const Class& double_class = Class::Handle( 1509 const Class& double_class =
1485 Isolate::Current()->object_store()->double_class()); 1510 Class::Handle(Isolate::Current()->object_store()->double_class());
1486 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. 1511 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register.
1487 __ swc1(F0, FieldAddress(V0, Double::value_offset())); 1512 __ swc1(F0, FieldAddress(V0, Double::value_offset()));
1488 __ Ret(); 1513 __ Ret();
1489 __ delay_slot()->swc1(F1, 1514 __ delay_slot()->swc1(F1,
1490 FieldAddress(V0, Double::value_offset() + kWordSize)); 1515 FieldAddress(V0, Double::value_offset() + kWordSize));
1491 __ Bind(&fall_through); 1516 __ Bind(&fall_through);
1492 } 1517 }
1493 1518
1494 1519
1495 void Intrinsifier::DoubleFromInteger(Assembler* assembler) { 1520 void Intrinsifier::DoubleFromInteger(Assembler* assembler) {
1496 Label fall_through; 1521 Label fall_through;
1497 1522
1498 __ lw(T0, Address(SP, 0 * kWordSize)); 1523 __ lw(T0, Address(SP, 0 * kWordSize));
1499 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); 1524 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
1500 __ bne(CMPRES1, ZR, &fall_through); 1525 __ bne(CMPRES1, ZR, &fall_through);
1501 1526
1502 // Is Smi. 1527 // Is Smi.
1503 __ SmiUntag(T0); 1528 __ SmiUntag(T0);
1504 __ mtc1(T0, F4); 1529 __ mtc1(T0, F4);
1505 __ cvtdw(D0, F4); 1530 __ cvtdw(D0, F4);
1506 const Class& double_class = Class::Handle( 1531 const Class& double_class =
1507 Isolate::Current()->object_store()->double_class()); 1532 Class::Handle(Isolate::Current()->object_store()->double_class());
1508 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. 1533 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register.
1509 __ swc1(F0, FieldAddress(V0, Double::value_offset())); 1534 __ swc1(F0, FieldAddress(V0, Double::value_offset()));
1510 __ Ret(); 1535 __ Ret();
1511 __ delay_slot()->swc1(F1, 1536 __ delay_slot()->swc1(F1,
1512 FieldAddress(V0, Double::value_offset() + kWordSize)); 1537 FieldAddress(V0, Double::value_offset() + kWordSize));
1513 __ Bind(&fall_through); 1538 __ Bind(&fall_through);
1514 } 1539 }
1515 1540
1516 1541
1517 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { 1542 void Intrinsifier::Double_getIsNaN(Assembler* assembler) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 __ Bind(&is_true); 1594 __ Bind(&is_true);
1570 __ LoadObject(V0, Bool::True()); 1595 __ LoadObject(V0, Bool::True());
1571 __ Ret(); 1596 __ Ret();
1572 1597
1573 __ Bind(&is_false); 1598 __ Bind(&is_false);
1574 __ LoadObject(V0, Bool::False()); 1599 __ LoadObject(V0, Bool::False());
1575 __ Ret(); 1600 __ Ret();
1576 1601
1577 __ Bind(&is_zero); 1602 __ Bind(&is_zero);
1578 // Check for negative zero by looking at the sign bit. 1603 // Check for negative zero by looking at the sign bit.
1579 __ mfc1(T0, F1); // Moves bits 32...63 of D0 to T0. 1604 __ mfc1(T0, F1); // Moves bits 32...63 of D0 to T0.
1580 __ srl(T0, T0, 31); // Get the sign bit down to bit 0 of T0. 1605 __ srl(T0, T0, 31); // Get the sign bit down to bit 0 of T0.
1581 __ andi(CMPRES1, T0, Immediate(1)); // Check if the bit is set. 1606 __ andi(CMPRES1, T0, Immediate(1)); // Check if the bit is set.
1582 __ bne(T0, ZR, &is_true); // Sign bit set. True. 1607 __ bne(T0, ZR, &is_true); // Sign bit set. True.
1583 __ b(&is_false); 1608 __ b(&is_false);
1584 } 1609 }
1585 1610
1586 1611
1587 void Intrinsifier::DoubleToInteger(Assembler* assembler) { 1612 void Intrinsifier::DoubleToInteger(Assembler* assembler) {
1588 __ lw(T0, Address(SP, 0 * kWordSize)); 1613 __ lw(T0, Address(SP, 0 * kWordSize));
1589 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag); 1614 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag);
1590 1615
1591 __ truncwd(F2, D0); 1616 __ truncwd(F2, D0);
1592 __ mfc1(V0, F2); 1617 __ mfc1(V0, F2);
(...skipping 10 matching lines...) Expand all
1603 } 1628 }
1604 1629
1605 1630
1606 void Intrinsifier::MathSqrt(Assembler* assembler) { 1631 void Intrinsifier::MathSqrt(Assembler* assembler) {
1607 Label fall_through, is_smi, double_op; 1632 Label fall_through, is_smi, double_op;
1608 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1633 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1609 // Argument is double and is in T0. 1634 // Argument is double and is in T0.
1610 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag); 1635 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag);
1611 __ Bind(&double_op); 1636 __ Bind(&double_op);
1612 __ sqrtd(D0, D1); 1637 __ sqrtd(D0, D1);
1613 const Class& double_class = Class::Handle( 1638 const Class& double_class =
1614 Isolate::Current()->object_store()->double_class()); 1639 Class::Handle(Isolate::Current()->object_store()->double_class());
1615 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. 1640 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register.
1616 __ swc1(F0, FieldAddress(V0, Double::value_offset())); 1641 __ swc1(F0, FieldAddress(V0, Double::value_offset()));
1617 __ Ret(); 1642 __ Ret();
1618 __ delay_slot()->swc1(F1, 1643 __ delay_slot()->swc1(F1,
1619 FieldAddress(V0, Double::value_offset() + kWordSize)); 1644 FieldAddress(V0, Double::value_offset() + kWordSize));
1620 1645
1621 __ Bind(&is_smi); 1646 __ Bind(&is_smi);
1622 __ SmiUntag(T0); 1647 __ SmiUntag(T0);
1623 __ mtc1(T0, F2); 1648 __ mtc1(T0, F2);
1624 __ b(&double_op); 1649 __ b(&double_op);
1625 __ delay_slot()->cvtdw(D1, F2); 1650 __ delay_slot()->cvtdw(D1, F2);
1626 __ Bind(&fall_through); 1651 __ Bind(&fall_through);
1627 } 1652 }
1628 1653
1629 1654
1630 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64; 1655 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
1631 // _state[kSTATE_LO] = state & _MASK_32; 1656 // _state[kSTATE_LO] = state & _MASK_32;
1632 // _state[kSTATE_HI] = state >> 32; 1657 // _state[kSTATE_HI] = state >> 32;
1633 void Intrinsifier::Random_nextState(Assembler* assembler) { 1658 void Intrinsifier::Random_nextState(Assembler* assembler) {
1634 const Library& math_lib = Library::Handle(Library::MathLibrary()); 1659 const Library& math_lib = Library::Handle(Library::MathLibrary());
1635 ASSERT(!math_lib.IsNull()); 1660 ASSERT(!math_lib.IsNull());
1636 const Class& random_class = Class::Handle( 1661 const Class& random_class =
1637 math_lib.LookupClassAllowPrivate(Symbols::_Random())); 1662 Class::Handle(math_lib.LookupClassAllowPrivate(Symbols::_Random()));
1638 ASSERT(!random_class.IsNull()); 1663 ASSERT(!random_class.IsNull());
1639 const Field& state_field = Field::ZoneHandle( 1664 const Field& state_field = Field::ZoneHandle(
1640 random_class.LookupInstanceFieldAllowPrivate(Symbols::_state())); 1665 random_class.LookupInstanceFieldAllowPrivate(Symbols::_state()));
1641 ASSERT(!state_field.IsNull()); 1666 ASSERT(!state_field.IsNull());
1642 const Field& random_A_field = Field::ZoneHandle( 1667 const Field& random_A_field = Field::ZoneHandle(
1643 random_class.LookupStaticFieldAllowPrivate(Symbols::_A())); 1668 random_class.LookupStaticFieldAllowPrivate(Symbols::_A()));
1644 ASSERT(!random_A_field.IsNull()); 1669 ASSERT(!random_A_field.IsNull());
1645 ASSERT(random_A_field.is_const()); 1670 ASSERT(random_A_field.is_const());
1646 const Instance& a_value = Instance::Handle(random_A_field.StaticValue()); 1671 const Instance& a_value = Instance::Handle(random_A_field.StaticValue());
1647 const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value(); 1672 const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1682 __ lw(T1, Address(SP, 1 * kWordSize)); 1707 __ lw(T1, Address(SP, 1 * kWordSize));
1683 __ beq(T0, T1, &is_true); 1708 __ beq(T0, T1, &is_true);
1684 __ LoadObject(V0, Bool::False()); 1709 __ LoadObject(V0, Bool::False());
1685 __ Ret(); 1710 __ Ret();
1686 __ Bind(&is_true); 1711 __ Bind(&is_true);
1687 __ LoadObject(V0, Bool::True()); 1712 __ LoadObject(V0, Bool::True());
1688 __ Ret(); 1713 __ Ret();
1689 } 1714 }
1690 1715
1691 1716
1692 enum RangeCheckCondition { 1717 enum RangeCheckCondition { kIfNotInRange, kIfInRange };
1693 kIfNotInRange, kIfInRange
1694 };
1695 1718
1696 1719
1697 static void RangeCheck(Assembler* assembler, 1720 static void RangeCheck(Assembler* assembler,
1698 Register val, 1721 Register val,
1699 Register tmp, 1722 Register tmp,
1700 intptr_t low, 1723 intptr_t low,
1701 intptr_t high, 1724 intptr_t high,
1702 RangeCheckCondition cc, 1725 RangeCheckCondition cc,
1703 Label* target) { 1726 Label* target) {
1704 __ AddImmediate(tmp, val, -low); 1727 __ AddImmediate(tmp, val, -low);
(...skipping 16 matching lines...) Expand all
1721 1744
1722 static void JumpIfNotInteger(Assembler* assembler, 1745 static void JumpIfNotInteger(Assembler* assembler,
1723 Register cid, 1746 Register cid,
1724 Register tmp, 1747 Register tmp,
1725 Label* target) { 1748 Label* target) {
1726 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target); 1749 RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target);
1727 } 1750 }
1728 1751
1729 1752
1730 static void JumpIfString(Assembler* assembler, 1753 static void JumpIfString(Assembler* assembler,
1731 Register cid, 1754 Register cid,
1732 Register tmp, 1755 Register tmp,
1733 Label* target) { 1756 Label* target) {
1734 RangeCheck(assembler, 1757 RangeCheck(assembler, cid, tmp, kOneByteStringCid, kExternalTwoByteStringCid,
1735 cid, 1758 kIfInRange, target);
1736 tmp,
1737 kOneByteStringCid,
1738 kExternalTwoByteStringCid,
1739 kIfInRange,
1740 target);
1741 } 1759 }
1742 1760
1743 1761
1744 static void JumpIfNotString(Assembler* assembler, 1762 static void JumpIfNotString(Assembler* assembler,
1745 Register cid, 1763 Register cid,
1746 Register tmp, 1764 Register tmp,
1747 Label* target) { 1765 Label* target) {
1748 RangeCheck(assembler, 1766 RangeCheck(assembler, cid, tmp, kOneByteStringCid, kExternalTwoByteStringCid,
1749 cid, 1767 kIfNotInRange, target);
1750 tmp,
1751 kOneByteStringCid,
1752 kExternalTwoByteStringCid,
1753 kIfNotInRange,
1754 target);
1755 } 1768 }
1756 1769
1757 1770
1758 // Return type quickly for simple types (not parameterized and not signature). 1771 // Return type quickly for simple types (not parameterized and not signature).
1759 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { 1772 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) {
1760 Label fall_through, use_canonical_type, not_integer, not_double; 1773 Label fall_through, use_canonical_type, not_integer, not_double;
1761 __ lw(T0, Address(SP, 0 * kWordSize)); 1774 __ lw(T0, Address(SP, 0 * kWordSize));
1762 __ LoadClassIdMayBeSmi(T1, T0); 1775 __ LoadClassIdMayBeSmi(T1, T0);
1763 1776
1764 // Closures are handled in the runtime. 1777 // Closures are handled in the runtime.
1765 __ BranchEqual(T1, Immediate(kClosureCid), &fall_through); 1778 __ BranchEqual(T1, Immediate(kClosureCid), &fall_through);
1766 1779
1767 __ BranchUnsignedGreaterEqual( 1780 __ BranchUnsignedGreaterEqual(T1, Immediate(kNumPredefinedCids),
1768 T1, Immediate(kNumPredefinedCids), &use_canonical_type); 1781 &use_canonical_type);
1769 1782
1770 __ BranchNotEqual(T1, Immediate(kDoubleCid), &not_double); 1783 __ BranchNotEqual(T1, Immediate(kDoubleCid), &not_double);
1771 // Object is a double. 1784 // Object is a double.
1772 __ LoadIsolate(T1); 1785 __ LoadIsolate(T1);
1773 __ LoadFromOffset(T1, T1, Isolate::object_store_offset()); 1786 __ LoadFromOffset(T1, T1, Isolate::object_store_offset());
1774 __ LoadFromOffset(V0, T1, ObjectStore::double_type_offset()); 1787 __ LoadFromOffset(V0, T1, ObjectStore::double_type_offset());
1775 __ Ret(); 1788 __ Ret();
1776 1789
1777 __ Bind(&not_double); 1790 __ Bind(&not_double);
1778 JumpIfNotInteger(assembler, T1, T2, &not_integer); 1791 JumpIfNotInteger(assembler, T1, T2, &not_integer);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1827 __ lhu(T1, FieldAddress(T2, Class::num_type_arguments_offset())); 1840 __ lhu(T1, FieldAddress(T2, Class::num_type_arguments_offset()));
1828 __ BranchNotEqual(T1, Immediate(0), &fall_through); 1841 __ BranchNotEqual(T1, Immediate(0), &fall_through);
1829 1842
1830 __ Bind(&equal); 1843 __ Bind(&equal);
1831 __ LoadObject(V0, Bool::True()); 1844 __ LoadObject(V0, Bool::True());
1832 __ Ret(); 1845 __ Ret();
1833 1846
1834 // Class ids are different. Check if we are comparing runtime types of 1847 // Class ids are different. Check if we are comparing runtime types of
1835 // two strings (with different representations) or two integers. 1848 // two strings (with different representations) or two integers.
1836 __ Bind(&different_cids); 1849 __ Bind(&different_cids);
1837 __ BranchUnsignedGreaterEqual( 1850 __ BranchUnsignedGreaterEqual(T1, Immediate(kNumPredefinedCids), &not_equal);
1838 T1, Immediate(kNumPredefinedCids), &not_equal);
1839 1851
1840 // Check if both are integers. 1852 // Check if both are integers.
1841 JumpIfNotInteger(assembler, T1, T0, &not_integer); 1853 JumpIfNotInteger(assembler, T1, T0, &not_integer);
1842 JumpIfInteger(assembler, T2, T0, &equal); 1854 JumpIfInteger(assembler, T2, T0, &equal);
1843 __ b(&not_equal); 1855 __ b(&not_equal);
1844 1856
1845 __ Bind(&not_integer); 1857 __ Bind(&not_integer);
1846 // Check if both are strings. 1858 // Check if both are strings.
1847 JumpIfNotString(assembler, T1, T0, &not_equal); 1859 JumpIfNotString(assembler, T1, T0, &not_equal);
1848 JumpIfString(assembler, T2, T0, &equal); 1860 JumpIfString(assembler, T2, T0, &equal);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1943 1955
1944 __ andi(CMPRES1, A1, Immediate(kSmiTagMask)); 1956 __ andi(CMPRES1, A1, Immediate(kSmiTagMask));
1945 __ bne(CMPRES1, ZR, &fall_through); // 'start' is not a Smi. 1957 __ bne(CMPRES1, ZR, &fall_through); // 'start' is not a Smi.
1946 1958
1947 __ LoadClassId(CMPRES1, A2); 1959 __ LoadClassId(CMPRES1, A2);
1948 __ BranchNotEqual(CMPRES1, Immediate(kOneByteStringCid), &fall_through); 1960 __ BranchNotEqual(CMPRES1, Immediate(kOneByteStringCid), &fall_through);
1949 1961
1950 __ LoadClassId(CMPRES1, A0); 1962 __ LoadClassId(CMPRES1, A0);
1951 __ BranchNotEqual(CMPRES1, Immediate(kOneByteStringCid), &try_two_byte); 1963 __ BranchNotEqual(CMPRES1, Immediate(kOneByteStringCid), &try_two_byte);
1952 1964
1953 GenerateSubstringMatchesSpecialization(assembler, 1965 GenerateSubstringMatchesSpecialization(assembler, kOneByteStringCid,
1954 kOneByteStringCid, 1966 kOneByteStringCid, &return_true,
1955 kOneByteStringCid,
1956 &return_true,
1957 &return_false); 1967 &return_false);
1958 1968
1959 __ Bind(&try_two_byte); 1969 __ Bind(&try_two_byte);
1960 __ LoadClassId(CMPRES1, A0); 1970 __ LoadClassId(CMPRES1, A0);
1961 __ BranchNotEqual(CMPRES1, Immediate(kTwoByteStringCid), &fall_through); 1971 __ BranchNotEqual(CMPRES1, Immediate(kTwoByteStringCid), &fall_through);
1962 1972
1963 GenerateSubstringMatchesSpecialization(assembler, 1973 GenerateSubstringMatchesSpecialization(assembler, kTwoByteStringCid,
1964 kTwoByteStringCid, 1974 kOneByteStringCid, &return_true,
1965 kOneByteStringCid,
1966 &return_true,
1967 &return_false); 1975 &return_false);
1968 1976
1969 __ Bind(&return_true); 1977 __ Bind(&return_true);
1970 __ LoadObject(V0, Bool::True()); 1978 __ LoadObject(V0, Bool::True());
1971 __ Ret(); 1979 __ Ret();
1972 1980
1973 __ Bind(&return_false); 1981 __ Bind(&return_false);
1974 __ LoadObject(V0, Bool::False()); 1982 __ LoadObject(V0, Bool::False());
1975 __ Ret(); 1983 __ Ret();
1976 1984
1977 __ Bind(&fall_through); 1985 __ Bind(&fall_through);
1978 } 1986 }
1979 1987
1980 1988
1981 void Intrinsifier::StringBaseCharAt(Assembler* assembler) { 1989 void Intrinsifier::StringBaseCharAt(Assembler* assembler) {
1982 Label fall_through, try_two_byte_string; 1990 Label fall_through, try_two_byte_string;
1983 1991
1984 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. 1992 __ lw(T1, Address(SP, 0 * kWordSize)); // Index.
1985 __ lw(T0, Address(SP, 1 * kWordSize)); // String. 1993 __ lw(T0, Address(SP, 1 * kWordSize)); // String.
1986 1994
1987 // Checks. 1995 // Checks.
1988 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); 1996 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
1989 __ bne(CMPRES1, ZR, &fall_through); // Index is not a Smi. 1997 __ bne(CMPRES1, ZR, &fall_through); // Index is not a Smi.
1990 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. 1998 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check.
1991 // Runtime throws exception. 1999 // Runtime throws exception.
1992 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); 2000 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through);
1993 __ LoadClassId(CMPRES1, T0); // Class ID check. 2001 __ LoadClassId(CMPRES1, T0); // Class ID check.
1994 __ BranchNotEqual( 2002 __ BranchNotEqual(CMPRES1, Immediate(kOneByteStringCid),
1995 CMPRES1, Immediate(kOneByteStringCid), &try_two_byte_string); 2003 &try_two_byte_string);
1996 2004
1997 // Grab byte and return. 2005 // Grab byte and return.
1998 __ SmiUntag(T1); 2006 __ SmiUntag(T1);
1999 __ addu(T2, T0, T1); 2007 __ addu(T2, T0, T1);
2000 __ lbu(T2, FieldAddress(T2, OneByteString::data_offset())); 2008 __ lbu(T2, FieldAddress(T2, OneByteString::data_offset()));
2001 __ BranchUnsignedGreaterEqual( 2009 __ BranchUnsignedGreaterEqual(
2002 T2, Immediate(Symbols::kNumberOfOneCharCodeSymbols), &fall_through); 2010 T2, Immediate(Symbols::kNumberOfOneCharCodeSymbols), &fall_through);
2003 __ lw(V0, Address(THR, Thread::predefined_symbols_address_offset())); 2011 __ lw(V0, Address(THR, Thread::predefined_symbols_address_offset()));
2004 __ AddImmediate(V0, Symbols::kNullCharCodeSymbolOffset * kWordSize); 2012 __ AddImmediate(V0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
2005 __ sll(T2, T2, 2); 2013 __ sll(T2, T2, 2);
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
2148 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, T2, T3, space)); 2156 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, T2, T3, space));
2149 2157
2150 // Initialize the tags. 2158 // Initialize the tags.
2151 // V0: new object start as a tagged pointer. 2159 // V0: new object start as a tagged pointer.
2152 // T1: new object end address. 2160 // T1: new object end address.
2153 // T2: allocation size. 2161 // T2: allocation size.
2154 { 2162 {
2155 Label overflow, done; 2163 Label overflow, done;
2156 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; 2164 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
2157 2165
2158 __ BranchUnsignedGreater( 2166 __ BranchUnsignedGreater(T2, Immediate(RawObject::SizeTag::kMaxSizeTag),
2159 T2, Immediate(RawObject::SizeTag::kMaxSizeTag), &overflow); 2167 &overflow);
2160 __ b(&done); 2168 __ b(&done);
2161 __ delay_slot()->sll(T2, T2, shift); 2169 __ delay_slot()->sll(T2, T2, shift);
2162 __ Bind(&overflow); 2170 __ Bind(&overflow);
2163 __ mov(T2, ZR); 2171 __ mov(T2, ZR);
2164 __ Bind(&done); 2172 __ Bind(&done);
2165 2173
2166 // Get the class index and insert it into the tags. 2174 // Get the class index and insert it into the tags.
2167 // T2: size and bit tags. 2175 // T2: size and bit tags.
2168 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); 2176 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));
2169 __ or_(T2, T2, TMP); 2177 __ or_(T2, T2, TMP);
2170 __ sw(T2, FieldAddress(V0, String::tags_offset())); // Store tags. 2178 __ sw(T2, FieldAddress(V0, String::tags_offset())); // Store tags.
2171 } 2179 }
2172 2180
2173 // Set the length field using the saved length (T6). 2181 // Set the length field using the saved length (T6).
2174 __ StoreIntoObjectNoBarrier(V0, 2182 __ StoreIntoObjectNoBarrier(V0, FieldAddress(V0, String::length_offset()),
2175 FieldAddress(V0, String::length_offset()),
2176 T6); 2183 T6);
2177 // Clear hash. 2184 // Clear hash.
2178 __ b(ok); 2185 __ b(ok);
2179 __ delay_slot()->sw(ZR, FieldAddress(V0, String::hash_offset())); 2186 __ delay_slot()->sw(ZR, FieldAddress(V0, String::hash_offset()));
2180 } 2187 }
2181 2188
2182 2189
2183 // Arg0: OneByteString (receiver). 2190 // Arg0: OneByteString (receiver).
2184 // Arg1: Start index as Smi. 2191 // Arg1: Start index as Smi.
2185 // Arg2: End index as Smi. 2192 // Arg2: End index as Smi.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2268 Label fall_through, is_true, is_false, loop; 2275 Label fall_through, is_true, is_false, loop;
2269 __ lw(T0, Address(SP, 1 * kWordSize)); // This. 2276 __ lw(T0, Address(SP, 1 * kWordSize)); // This.
2270 __ lw(T1, Address(SP, 0 * kWordSize)); // Other. 2277 __ lw(T1, Address(SP, 0 * kWordSize)); // Other.
2271 2278
2272 // Are identical? 2279 // Are identical?
2273 __ beq(T0, T1, &is_true); 2280 __ beq(T0, T1, &is_true);
2274 2281
2275 // Is other OneByteString? 2282 // Is other OneByteString?
2276 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); 2283 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
2277 __ beq(CMPRES1, ZR, &fall_through); // Other is Smi. 2284 __ beq(CMPRES1, ZR, &fall_through); // Other is Smi.
2278 __ LoadClassId(CMPRES1, T1); // Class ID check. 2285 __ LoadClassId(CMPRES1, T1); // Class ID check.
2279 __ BranchNotEqual(CMPRES1, Immediate(string_cid), &fall_through); 2286 __ BranchNotEqual(CMPRES1, Immediate(string_cid), &fall_through);
2280 2287
2281 // Have same length? 2288 // Have same length?
2282 __ lw(T2, FieldAddress(T0, String::length_offset())); 2289 __ lw(T2, FieldAddress(T0, String::length_offset()));
2283 __ lw(T3, FieldAddress(T1, String::length_offset())); 2290 __ lw(T3, FieldAddress(T1, String::length_offset()));
2284 __ bne(T2, T3, &is_false); 2291 __ bne(T2, T3, &is_false);
2285 2292
2286 // Check contents, no fall-through possible. 2293 // Check contents, no fall-through possible.
2287 ASSERT((string_cid == kOneByteStringCid) || 2294 ASSERT((string_cid == kOneByteStringCid) ||
2288 (string_cid == kTwoByteStringCid)); 2295 (string_cid == kTwoByteStringCid));
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2360 } 2367 }
2361 2368
2362 2369
2363 // On stack: user tag (+0). 2370 // On stack: user tag (+0).
2364 void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) { 2371 void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) {
2365 // T1: Isolate. 2372 // T1: Isolate.
2366 __ LoadIsolate(T1); 2373 __ LoadIsolate(T1);
2367 // V0: Current user tag. 2374 // V0: Current user tag.
2368 __ lw(V0, Address(T1, Isolate::current_tag_offset())); 2375 __ lw(V0, Address(T1, Isolate::current_tag_offset()));
2369 // T2: UserTag. 2376 // T2: UserTag.
2370 __ lw(T2, Address(SP, + 0 * kWordSize)); 2377 __ lw(T2, Address(SP, +0 * kWordSize));
2371 // Set Isolate::current_tag_. 2378 // Set Isolate::current_tag_.
2372 __ sw(T2, Address(T1, Isolate::current_tag_offset())); 2379 __ sw(T2, Address(T1, Isolate::current_tag_offset()));
2373 // T2: UserTag's tag. 2380 // T2: UserTag's tag.
2374 __ lw(T2, FieldAddress(T2, UserTag::tag_offset())); 2381 __ lw(T2, FieldAddress(T2, UserTag::tag_offset()));
2375 // Set Isolate::user_tag_. 2382 // Set Isolate::user_tag_.
2376 __ sw(T2, Address(T1, Isolate::user_tag_offset())); 2383 __ sw(T2, Address(T1, Isolate::user_tag_offset()));
2377 __ Ret(); 2384 __ Ret();
2378 __ delay_slot()->sw(T2, Address(T1, Isolate::user_tag_offset())); 2385 __ delay_slot()->sw(T2, Address(T1, Isolate::user_tag_offset()));
2379 } 2386 }
2380 2387
(...skipping 24 matching lines...) Expand all
2405 __ lw(T0, Address(V0, TimelineStream::enabled_offset())); 2412 __ lw(T0, Address(V0, TimelineStream::enabled_offset()));
2406 __ LoadObject(V0, Bool::True()); 2413 __ LoadObject(V0, Bool::True());
2407 __ LoadObject(V1, Bool::False()); 2414 __ LoadObject(V1, Bool::False());
2408 __ Ret(); 2415 __ Ret();
2409 __ delay_slot()->movz(V0, V1, T0); // V0 = (T0 == 0) ? V1 : V0. 2416 __ delay_slot()->movz(V0, V1, T0); // V0 = (T0 == 0) ? V1 : V0.
2410 } 2417 }
2411 2418
2412 } // namespace dart 2419 } // namespace dart
2413 2420
2414 #endif // defined TARGET_ARCH_MIPS 2421 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_ia32.cc ('k') | runtime/vm/intrinsifier_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698