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

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

Issue 59613005: Merge (x & y) == 0 pattern to emit a single test instruction. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 | Annotate | Revision Log
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 13 matching lines...) Expand all
24 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; 24 const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
25 const intptr_t kArrayLengthOffset = 0 * kWordSize; 25 const intptr_t kArrayLengthOffset = 0 * kWordSize;
26 Label fall_through; 26 Label fall_through;
27 27
28 // Compute the size to be allocated, it is based on the array length 28 // Compute the size to be allocated, it is based on the array length
29 // and is computed as: 29 // and is computed as:
30 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). 30 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
31 __ lw(T3, Address(SP, kArrayLengthOffset)); // Array length. 31 __ lw(T3, Address(SP, kArrayLengthOffset)); // Array length.
32 32
33 // Check that length is a positive Smi. 33 // Check that length is a positive Smi.
34 __ andi(CMPRES, T3, Immediate(kSmiTagMask)); 34 __ andi(CMPRES1, T3, Immediate(kSmiTagMask));
35 __ bne(CMPRES, ZR, &fall_through); 35 __ bne(CMPRES1, ZR, &fall_through);
36 __ bltz(T3, &fall_through); 36 __ bltz(T3, &fall_through);
37 37
38 // Check for maximum allowed length. 38 // Check for maximum allowed length.
39 const intptr_t max_len = 39 const intptr_t max_len =
40 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); 40 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements));
41 __ BranchUnsignedGreater(T3, max_len, &fall_through); 41 __ BranchUnsignedGreater(T3, max_len, &fall_through);
42 42
43 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; 43 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
44 __ LoadImmediate(T2, fixed_size); 44 __ LoadImmediate(T2, fixed_size);
45 __ sll(T3, T3, 1); // T3 is a Smi. 45 __ sll(T3, T3, 1); // T3 is a Smi.
46 __ addu(T2, T2, T3); 46 __ addu(T2, T2, T3);
47 ASSERT(kSmiTagShift == 1); 47 ASSERT(kSmiTagShift == 1);
48 __ LoadImmediate(T3, ~(kObjectAlignment - 1)); 48 __ LoadImmediate(T3, ~(kObjectAlignment - 1));
49 __ and_(T2, T2, T3); 49 __ and_(T2, T2, T3);
50 50
51 // T2: Allocation size. 51 // T2: Allocation size.
52 52
53 Isolate* isolate = Isolate::Current(); 53 Isolate* isolate = Isolate::Current();
54 Heap* heap = isolate->heap(); 54 Heap* heap = isolate->heap();
55 55
56 __ LoadImmediate(T3, heap->TopAddress()); 56 __ LoadImmediate(T3, heap->TopAddress());
57 __ lw(T0, Address(T3, 0)); // Potential new object start. 57 __ lw(T0, Address(T3, 0)); // Potential new object start.
58 58
59 __ AdduDetectOverflow(T1, T0, T2, CMPRES); // Potential next object start. 59 __ AdduDetectOverflow(T1, T0, T2, CMPRES1); // Potential next object start.
60 __ bltz(CMPRES, &fall_through); // CMPRES < 0 on overflow. 60 __ bltz(CMPRES1, &fall_through); // CMPRES1 < 0 on overflow.
61 61
62 // Check if the allocation fits into the remaining space. 62 // Check if the allocation fits into the remaining space.
63 // T0: potential new object start. 63 // T0: potential new object start.
64 // T1: potential next object start. 64 // T1: potential next object start.
65 // T2: allocation size. 65 // T2: allocation size.
66 __ LoadImmediate(T4, heap->TopAddress()); 66 __ LoadImmediate(T4, heap->TopAddress());
67 __ lw(T4, Address(T4, 0)); 67 __ lw(T4, Address(T4, 0));
68 __ BranchUnsignedGreaterEqual(T1, T4, &fall_through); 68 __ BranchUnsignedGreaterEqual(T1, T4, &fall_through);
69 69
70 // Successfully allocated the object(s), now update top to point to 70 // Successfully allocated the object(s), now update top to point to
(...skipping 12 matching lines...) Expand all
83 83
84 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); 84 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow);
85 __ b(&done); 85 __ b(&done);
86 __ delay_slot()->sll(T2, T2, shift); 86 __ delay_slot()->sll(T2, T2, shift);
87 __ Bind(&overflow); 87 __ Bind(&overflow);
88 __ mov(T2, ZR); 88 __ mov(T2, ZR);
89 __ Bind(&done); 89 __ Bind(&done);
90 90
91 // Get the class index and insert it into the tags. 91 // Get the class index and insert it into the tags.
92 // T2: size and bit tags. 92 // T2: size and bit tags.
93 __ LoadImmediate(TMP1, RawObject::ClassIdTag::encode(cls.id())); 93 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id()));
94 __ or_(T2, T2, TMP1); 94 __ or_(T2, T2, TMP);
95 __ sw(T2, FieldAddress(T0, Array::tags_offset())); // Store tags. 95 __ sw(T2, FieldAddress(T0, Array::tags_offset())); // Store tags.
96 } 96 }
97 97
98 // T0: new object start as a tagged pointer. 98 // T0: new object start as a tagged pointer.
99 // T1: new object end address. 99 // T1: new object end address.
100 // Store the type argument field. 100 // Store the type argument field.
101 __ lw(T2, Address(SP, kTypeArgumentsOffset)); // Type argument. 101 __ lw(T2, Address(SP, kTypeArgumentsOffset)); // Type argument.
102 __ StoreIntoObjectNoBarrier(T0, 102 __ StoreIntoObjectNoBarrier(T0,
103 FieldAddress(T0, Array::type_arguments_offset()), 103 FieldAddress(T0, Array::type_arguments_offset()),
104 T2); 104 T2);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { 143 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) {
144 return Array_getLength(assembler); 144 return Array_getLength(assembler);
145 } 145 }
146 146
147 147
148 void Intrinsifier::Array_getIndexed(Assembler* assembler) { 148 void Intrinsifier::Array_getIndexed(Assembler* assembler) {
149 Label fall_through; 149 Label fall_through;
150 150
151 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index 151 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index
152 152
153 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); 153 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
154 __ bne(CMPRES, ZR, &fall_through); // Index is not an smi, fall through 154 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through
155 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array 155 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array
156 156
157 // range check 157 // range check
158 __ lw(T2, FieldAddress(T1, Array::length_offset())); 158 __ lw(T2, FieldAddress(T1, Array::length_offset()));
159 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); 159 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
160 160
161 ASSERT(kSmiTagShift == 1); 161 ASSERT(kSmiTagShift == 1);
162 // array element at T1 + T0*2 + Array::data_offset - 1 162 // array element at T1 + T0*2 + Array::data_offset - 1
163 __ sll(T2, T0, 1); 163 __ sll(T2, T0, 1);
164 __ addu(T2, T1, T2); 164 __ addu(T2, T1, T2);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 // Check if it's dynamic. 210 // Check if it's dynamic.
211 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. 211 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs.
212 __ LoadClassId(CMPRES1, T1); 212 __ LoadClassId(CMPRES1, T1);
213 __ BranchNotEqual(CMPRES1, kTypeArgumentsCid, &fall_through); 213 __ BranchNotEqual(CMPRES1, kTypeArgumentsCid, &fall_through);
214 214
215 // Get type at index 0. 215 // Get type at index 0.
216 __ lw(T0, FieldAddress(T1, TypeArguments::type_at_offset(0))); 216 __ lw(T0, FieldAddress(T1, TypeArguments::type_at_offset(0)));
217 __ BranchEqual(T0, Type::ZoneHandle(Type::DynamicType()), &checked_ok); 217 __ BranchEqual(T0, Type::ZoneHandle(Type::DynamicType()), &checked_ok);
218 218
219 // Check for int and num. 219 // Check for int and num.
220 __ andi(CMPRES, T2, Immediate(kSmiTagMask)); 220 __ andi(CMPRES1, T2, Immediate(kSmiTagMask));
221 __ bne(CMPRES, ZR, &fall_through); // Non-smi value. 221 __ bne(CMPRES1, ZR, &fall_through); // Non-smi value.
222 222
223 __ BranchEqual(T0, Type::ZoneHandle(Type::IntType()), &checked_ok); 223 __ BranchEqual(T0, Type::ZoneHandle(Type::IntType()), &checked_ok);
224 __ BranchNotEqual(T0, Type::ZoneHandle(Type::Number()), &fall_through); 224 __ BranchNotEqual(T0, Type::ZoneHandle(Type::Number()), &fall_through);
225 __ Bind(&checked_ok); 225 __ Bind(&checked_ok);
226 } 226 }
227 __ lw(T1, Address(SP, 1 * kWordSize)); // Index. 227 __ lw(T1, Address(SP, 1 * kWordSize)); // Index.
228 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); 228 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
229 // Index not Smi. 229 // Index not Smi.
230 __ bne(CMPRES, ZR, &fall_through); 230 __ bne(CMPRES1, ZR, &fall_through);
231 231
232 __ lw(T0, Address(SP, 2 * kWordSize)); // Array. 232 __ lw(T0, Address(SP, 2 * kWordSize)); // Array.
233 // Range check. 233 // Range check.
234 __ lw(T3, FieldAddress(T0, Array::length_offset())); // Array length. 234 __ lw(T3, FieldAddress(T0, Array::length_offset())); // Array length.
235 // Runtime throws exception. 235 // Runtime throws exception.
236 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); 236 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through);
237 237
238 // Note that T1 is Smi, i.e, times 2. 238 // Note that T1 is Smi, i.e, times 2.
239 ASSERT(kSmiTagShift == 1); 239 ASSERT(kSmiTagShift == 1);
240 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. 240 __ lw(T2, Address(SP, 0 * kWordSize)); // Value.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 __ Ret(); 330 __ Ret();
331 __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset())); 331 __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset()));
332 } 332 }
333 333
334 334
335 void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { 335 void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) {
336 Label fall_through; 336 Label fall_through;
337 337
338 __ lw(T0, Address(SP, 0 * kWordSize)); // Index 338 __ lw(T0, Address(SP, 0 * kWordSize)); // Index
339 339
340 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); 340 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
341 __ bne(CMPRES, ZR, &fall_through); // Index is not an smi, fall through 341 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through
342 __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize)); // Array 342 __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize)); // Array
343 343
344 // range check 344 // range check
345 __ lw(T2, FieldAddress(T1, GrowableObjectArray::length_offset())); 345 __ lw(T2, FieldAddress(T1, GrowableObjectArray::length_offset()));
346 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); 346 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
347 347
348 __ lw(T2, FieldAddress(T1, GrowableObjectArray::data_offset())); // data 348 __ lw(T2, FieldAddress(T1, GrowableObjectArray::data_offset())); // data
349 349
350 ASSERT(kSmiTagShift == 1); 350 ASSERT(kSmiTagShift == 1);
351 // array element at T2 + T0 * 2 + Array::data_offset - 1 351 // array element at T2 + T0 * 2 + Array::data_offset - 1
352 __ sll(T3, T0, 1); 352 __ sll(T3, T0, 1);
353 __ addu(T2, T2, T3); 353 __ addu(T2, T2, T3);
354 __ Ret(); 354 __ Ret();
355 __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset())); 355 __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset()));
356 __ Bind(&fall_through); 356 __ Bind(&fall_through);
357 } 357 }
358 358
359 359
360 // Set value into growable object array at specified index. 360 // Set value into growable object array at specified index.
361 // On stack: growable array (+2), index (+1), value (+0). 361 // On stack: growable array (+2), index (+1), value (+0).
362 void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { 362 void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) {
363 if (FLAG_enable_type_checks) { 363 if (FLAG_enable_type_checks) {
364 return; 364 return;
365 } 365 }
366 Label fall_through; 366 Label fall_through;
367 __ lw(T1, Address(SP, 1 * kWordSize)); // Index. 367 __ lw(T1, Address(SP, 1 * kWordSize)); // Index.
368 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); 368 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
369 __ bne(CMPRES, ZR, &fall_through); // Non-smi index. 369 __ bne(CMPRES1, ZR, &fall_through); // Non-smi index.
370 __ delay_slot()->lw(T0, Address(SP, 2 * kWordSize)); // GrowableArray. 370 __ delay_slot()->lw(T0, Address(SP, 2 * kWordSize)); // GrowableArray.
371 // Range check using _length field. 371 // Range check using _length field.
372 __ lw(T2, FieldAddress(T0, GrowableObjectArray::length_offset())); 372 __ lw(T2, FieldAddress(T0, GrowableObjectArray::length_offset()));
373 // Runtime throws exception. 373 // Runtime throws exception.
374 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); 374 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through);
375 __ lw(T0, FieldAddress(T0, GrowableObjectArray::data_offset())); // data. 375 __ lw(T0, FieldAddress(T0, GrowableObjectArray::data_offset())); // data.
376 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. 376 __ lw(T2, Address(SP, 0 * kWordSize)); // Value.
377 // Note that T1 is Smi, i.e, times 2. 377 // Note that T1 is Smi, i.e, times 2.
378 ASSERT(kSmiTagShift == 1); 378 ASSERT(kSmiTagShift == 1);
379 __ sll(T1, T1, 1); 379 __ sll(T1, T1, 1);
380 __ addu(T1, T0, T1); 380 __ addu(T1, T0, T1);
381 __ StoreIntoObject(T0, 381 __ StoreIntoObject(T0,
382 FieldAddress(T1, Array::data_offset()), 382 FieldAddress(T1, Array::data_offset()),
383 T2); 383 T2);
384 __ Ret(); 384 __ Ret();
385 __ Bind(&fall_through); 385 __ Bind(&fall_through);
386 } 386 }
387 387
388 388
389 // Set length of growable object array. The length cannot 389 // Set length of growable object array. The length cannot
390 // be greater than the length of the data container. 390 // be greater than the length of the data container.
391 // On stack: growable array (+1), length (+0). 391 // On stack: growable array (+1), length (+0).
392 void Intrinsifier::GrowableList_setLength(Assembler* assembler) { 392 void Intrinsifier::GrowableList_setLength(Assembler* assembler) {
393 Label fall_through; 393 Label fall_through;
394 __ lw(T1, Address(SP, 0 * kWordSize)); // Length value. 394 __ lw(T1, Address(SP, 0 * kWordSize)); // Length value.
395 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); 395 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
396 __ bne(CMPRES, ZR, &fall_through); // Non-smi length. 396 __ bne(CMPRES1, ZR, &fall_through); // Non-smi length.
397 __ delay_slot()->lw(T0, Address(SP, 1 * kWordSize)); // Growable array. 397 __ delay_slot()->lw(T0, Address(SP, 1 * kWordSize)); // Growable array.
398 __ Ret(); 398 __ Ret();
399 __ delay_slot()->sw(T1, 399 __ delay_slot()->sw(T1,
400 FieldAddress(T0, GrowableObjectArray::length_offset())); 400 FieldAddress(T0, GrowableObjectArray::length_offset()));
401 __ Bind(&fall_through); 401 __ Bind(&fall_through);
402 } 402 }
403 403
404 404
405 // Set data of growable object array. 405 // Set data of growable object array.
406 // On stack: growable array (+1), data (+0). 406 // On stack: growable array (+1), data (+0).
407 void Intrinsifier::GrowableList_setData(Assembler* assembler) { 407 void Intrinsifier::GrowableList_setData(Assembler* assembler) {
408 if (FLAG_enable_type_checks) { 408 if (FLAG_enable_type_checks) {
409 return; 409 return;
410 } 410 }
411 Label fall_through; 411 Label fall_through;
412 __ lw(T1, Address(SP, 0 * kWordSize)); // Data. 412 __ lw(T1, Address(SP, 0 * kWordSize)); // Data.
413 // Check that data is an ObjectArray. 413 // Check that data is an ObjectArray.
414 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); 414 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
415 __ beq(CMPRES, ZR, &fall_through); // Data is Smi. 415 __ beq(CMPRES1, ZR, &fall_through); // Data is Smi.
416 __ LoadClassId(CMPRES1, T1); 416 __ LoadClassId(CMPRES1, T1);
417 __ BranchNotEqual(CMPRES1, kArrayCid, &fall_through); 417 __ BranchNotEqual(CMPRES1, kArrayCid, &fall_through);
418 __ lw(T0, Address(SP, 1 * kWordSize)); // Growable array. 418 __ lw(T0, Address(SP, 1 * kWordSize)); // Growable array.
419 __ StoreIntoObject(T0, 419 __ StoreIntoObject(T0,
420 FieldAddress(T0, GrowableObjectArray::data_offset()), 420 FieldAddress(T0, GrowableObjectArray::data_offset()),
421 T1); 421 T1);
422 __ Ret(); 422 __ Ret();
423 __ Bind(&fall_through); 423 __ Bind(&fall_through);
424 } 424 }
425 425
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 __ Bind(&fall_through); 457 __ Bind(&fall_through);
458 } 458 }
459 459
460 460
461 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \ 461 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \
462 Label fall_through; \ 462 Label fall_through; \
463 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \ 463 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \
464 __ lw(T2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \ 464 __ lw(T2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \
465 /* Check that length is a positive Smi. */ \ 465 /* Check that length is a positive Smi. */ \
466 /* T2: requested array length argument. */ \ 466 /* T2: requested array length argument. */ \
467 __ andi(CMPRES, T2, Immediate(kSmiTagMask)); \ 467 __ andi(CMPRES1, T2, Immediate(kSmiTagMask)); \
468 __ bne(CMPRES, ZR, &fall_through); \ 468 __ bne(CMPRES1, ZR, &fall_through); \
469 __ BranchSignedLess(T2, 0, &fall_through); \ 469 __ BranchSignedLess(T2, 0, &fall_through); \
470 __ SmiUntag(T2); \ 470 __ SmiUntag(T2); \
471 /* Check for maximum allowed length. */ \ 471 /* Check for maximum allowed length. */ \
472 /* T2: untagged array length. */ \ 472 /* T2: untagged array length. */ \
473 __ BranchSignedGreater(T2, max_len, &fall_through); \ 473 __ BranchSignedGreater(T2, max_len, &fall_through); \
474 __ sll(T2, T2, scale_shift); \ 474 __ sll(T2, T2, scale_shift); \
475 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ 475 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \
476 __ AddImmediate(T2, fixed_size); \ 476 __ AddImmediate(T2, fixed_size); \
477 __ LoadImmediate(TMP, -kObjectAlignment); \ 477 __ LoadImmediate(TMP, -kObjectAlignment); \
478 __ and_(T2, T2, TMP); \ 478 __ and_(T2, T2, TMP); \
479 Heap* heap = Isolate::Current()->heap(); \ 479 Heap* heap = Isolate::Current()->heap(); \
480 \ 480 \
481 __ LoadImmediate(V0, heap->TopAddress()); \ 481 __ LoadImmediate(V0, heap->TopAddress()); \
482 __ lw(V0, Address(V0, 0)); \ 482 __ lw(V0, Address(V0, 0)); \
483 \ 483 \
484 /* T2: allocation size. */ \ 484 /* T2: allocation size. */ \
485 __ AdduDetectOverflow(T1, V0, T2, CMPRES); \ 485 __ AdduDetectOverflow(T1, V0, T2, CMPRES1); \
486 __ bltz(CMPRES, &fall_through); \ 486 __ bltz(CMPRES1, &fall_through); \
487 \ 487 \
488 /* Check if the allocation fits into the remaining space. */ \ 488 /* Check if the allocation fits into the remaining space. */ \
489 /* V0: potential new object start. */ \ 489 /* V0: potential new object start. */ \
490 /* T1: potential next object start. */ \ 490 /* T1: potential next object start. */ \
491 /* T2: allocation size. */ \ 491 /* T2: allocation size. */ \
492 __ LoadImmediate(T3, heap->EndAddress()); \ 492 __ LoadImmediate(T3, heap->EndAddress()); \
493 __ lw(T3, Address(T3, 0)); \ 493 __ lw(T3, Address(T3, 0)); \
494 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); \ 494 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); \
495 \ 495 \
496 /* Successfully allocated the object(s), now update top to point to */ \ 496 /* Successfully allocated the object(s), now update top to point to */ \
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 } 581 }
582 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR) 582 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
583 #undef TYPED_DATA_ALLOCATOR 583 #undef TYPED_DATA_ALLOCATOR
584 584
585 585
586 // Loads args from stack into T0 and T1 586 // Loads args from stack into T0 and T1
587 // Tests if they are smis, jumps to label not_smi if not. 587 // Tests if they are smis, jumps to label not_smi if not.
588 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { 588 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
589 __ lw(T0, Address(SP, 0 * kWordSize)); 589 __ lw(T0, Address(SP, 0 * kWordSize));
590 __ lw(T1, Address(SP, 1 * kWordSize)); 590 __ lw(T1, Address(SP, 1 * kWordSize));
591 __ or_(CMPRES, T0, T1); 591 __ or_(CMPRES1, T0, T1);
592 __ andi(CMPRES, CMPRES, Immediate(kSmiTagMask)); 592 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask));
593 __ bne(CMPRES, ZR, not_smi); 593 __ bne(CMPRES1, ZR, not_smi);
594 return; 594 return;
595 } 595 }
596 596
597 597
598 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) { 598 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
599 Label fall_through; 599 Label fall_through;
600 600
601 TestBothArgumentsSmis(assembler, &fall_through); // Checks two Smis. 601 TestBothArgumentsSmis(assembler, &fall_through); // Checks two Smis.
602 __ AdduDetectOverflow(V0, T0, T1, CMPRES); // Add. 602 __ AdduDetectOverflow(V0, T0, T1, CMPRES1); // Add.
603 __ bltz(CMPRES, &fall_through); // Fall through on overflow. 603 __ bltz(CMPRES1, &fall_through); // Fall through on overflow.
604 __ Ret(); // Nothing in branch delay slot. 604 __ Ret(); // Nothing in branch delay slot.
605 __ Bind(&fall_through); 605 __ Bind(&fall_through);
606 } 606 }
607 607
608 608
609 void Intrinsifier::Integer_add(Assembler* assembler) { 609 void Intrinsifier::Integer_add(Assembler* assembler) {
610 return Integer_addFromInteger(assembler); 610 return Integer_addFromInteger(assembler);
611 } 611 }
612 612
613 613
614 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) { 614 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
615 Label fall_through; 615 Label fall_through;
616 616
617 TestBothArgumentsSmis(assembler, &fall_through); 617 TestBothArgumentsSmis(assembler, &fall_through);
618 __ SubuDetectOverflow(V0, T0, T1, CMPRES); // Subtract. 618 __ SubuDetectOverflow(V0, T0, T1, CMPRES1); // Subtract.
619 __ bltz(CMPRES, &fall_through); // Fall through on overflow. 619 __ bltz(CMPRES1, &fall_through); // Fall through on overflow.
620 __ Ret(); 620 __ Ret();
621 __ Bind(&fall_through); 621 __ Bind(&fall_through);
622 } 622 }
623 623
624 624
625 void Intrinsifier::Integer_sub(Assembler* assembler) { 625 void Intrinsifier::Integer_sub(Assembler* assembler) {
626 Label fall_through; 626 Label fall_through;
627 627
628 TestBothArgumentsSmis(assembler, &fall_through); 628 TestBothArgumentsSmis(assembler, &fall_through);
629 __ SubuDetectOverflow(V0, T1, T0, CMPRES); // Subtract. 629 __ SubuDetectOverflow(V0, T1, T0, CMPRES1); // Subtract.
630 __ bltz(CMPRES, &fall_through); // Fall through on overflow. 630 __ bltz(CMPRES1, &fall_through); // Fall through on overflow.
631 __ Ret(); // Nothing in branch delay slot. 631 __ Ret(); // Nothing in branch delay slot.
632 __ Bind(&fall_through); 632 __ Bind(&fall_through);
633 } 633 }
634 634
635 635
636 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { 636 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
637 Label fall_through; 637 Label fall_through;
638 638
639 TestBothArgumentsSmis(assembler, &fall_through); // checks two smis 639 TestBothArgumentsSmis(assembler, &fall_through); // checks two smis
640 __ SmiUntag(T0); // untags T0. only want result shifted by one 640 __ SmiUntag(T0); // untags T0. only want result shifted by one
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 // res = res - right; 699 // res = res - right;
700 // } else { 700 // } else {
701 // res = res + right; 701 // res = res + right;
702 // } 702 // }
703 // } 703 // }
704 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) { 704 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) {
705 Label fall_through, subtract; 705 Label fall_through, subtract;
706 // Test arguments for smi. 706 // Test arguments for smi.
707 __ lw(T1, Address(SP, 0 * kWordSize)); 707 __ lw(T1, Address(SP, 0 * kWordSize));
708 __ lw(T0, Address(SP, 1 * kWordSize)); 708 __ lw(T0, Address(SP, 1 * kWordSize));
709 __ or_(CMPRES, T0, T1); 709 __ or_(CMPRES1, T0, T1);
710 __ andi(CMPRES, CMPRES, Immediate(kSmiTagMask)); 710 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask));
711 __ bne(CMPRES, ZR, &fall_through); 711 __ bne(CMPRES1, ZR, &fall_through);
712 // T1: Tagged left (dividend). 712 // T1: Tagged left (dividend).
713 // T0: Tagged right (divisor). 713 // T0: Tagged right (divisor).
714 // Check if modulo by zero -> exception thrown in main function. 714 // Check if modulo by zero -> exception thrown in main function.
715 __ beq(T0, ZR, &fall_through); 715 __ beq(T0, ZR, &fall_through);
716 EmitRemainderOperation(assembler); 716 EmitRemainderOperation(assembler);
717 // Untagged right in T0. Untagged remainder result in V0. 717 // Untagged right in T0. Untagged remainder result in V0.
718 718
719 Label done; 719 Label done;
720 __ bgez(V0, &done); 720 __ bgez(V0, &done);
721 __ bltz(T0, &subtract); 721 __ bltz(T0, &subtract);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 __ Ret(); 770 __ Ret();
771 __ delay_slot()->SmiTag(V0); 771 __ delay_slot()->SmiTag(V0);
772 __ Bind(&fall_through); 772 __ Bind(&fall_through);
773 } 773 }
774 774
775 775
776 void Intrinsifier::Integer_negate(Assembler* assembler) { 776 void Intrinsifier::Integer_negate(Assembler* assembler) {
777 Label fall_through; 777 Label fall_through;
778 778
779 __ lw(T0, Address(SP, + 0 * kWordSize)); // Grabs first argument. 779 __ lw(T0, Address(SP, + 0 * kWordSize)); // Grabs first argument.
780 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); // Test for Smi. 780 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); // Test for Smi.
781 __ bne(CMPRES, ZR, &fall_through); // Fall through if not a Smi. 781 __ bne(CMPRES1, ZR, &fall_through); // Fall through if not a Smi.
782 __ SubuDetectOverflow(V0, ZR, T0, CMPRES); 782 __ SubuDetectOverflow(V0, ZR, T0, CMPRES1);
783 __ bltz(CMPRES, &fall_through); // There was overflow. 783 __ bltz(CMPRES1, &fall_through); // There was overflow.
784 __ Ret(); 784 __ Ret();
785 __ Bind(&fall_through); 785 __ Bind(&fall_through);
786 } 786 }
787 787
788 788
789 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) { 789 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
790 Label fall_through; 790 Label fall_through;
791 791
792 TestBothArgumentsSmis(assembler, &fall_through); // Checks two smis. 792 TestBothArgumentsSmis(assembler, &fall_through); // Checks two smis.
793 __ Ret(); 793 __ Ret();
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 __ Bind(&fall_through); 880 __ Bind(&fall_through);
881 } 881 }
882 882
883 883
884 static void Get64SmiOrMint(Assembler* assembler, 884 static void Get64SmiOrMint(Assembler* assembler,
885 Register res_hi, 885 Register res_hi,
886 Register res_lo, 886 Register res_lo,
887 Register reg, 887 Register reg,
888 Label* not_smi_or_mint) { 888 Label* not_smi_or_mint) {
889 Label not_smi, done; 889 Label not_smi, done;
890 __ andi(CMPRES, reg, Immediate(kSmiTagMask)); 890 __ andi(CMPRES1, reg, Immediate(kSmiTagMask));
891 __ bne(CMPRES, ZR, &not_smi); 891 __ bne(CMPRES1, ZR, &not_smi);
892 __ SmiUntag(reg); 892 __ SmiUntag(reg);
893 893
894 // Sign extend to 64 bit 894 // Sign extend to 64 bit
895 __ mov(res_lo, reg); 895 __ mov(res_lo, reg);
896 __ b(&done); 896 __ b(&done);
897 __ delay_slot()->sra(res_hi, reg, 31); 897 __ delay_slot()->sra(res_hi, reg, 31);
898 898
899 __ Bind(&not_smi); 899 __ Bind(&not_smi);
900 __ LoadClassId(CMPRES1, reg); 900 __ LoadClassId(CMPRES1, reg);
901 __ BranchNotEqual(CMPRES1, kMintCid, not_smi_or_mint); 901 __ BranchNotEqual(CMPRES1, kMintCid, not_smi_or_mint);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 // This is called for Smi, Mint and Bigint receivers. The right argument 1008 // This is called for Smi, Mint and Bigint receivers. The right argument
1009 // can be Smi, Mint, Bigint or double. 1009 // can be Smi, Mint, Bigint or double.
1010 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) { 1010 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
1011 Label fall_through, true_label, check_for_mint; 1011 Label fall_through, true_label, check_for_mint;
1012 // For integer receiver '===' check first. 1012 // For integer receiver '===' check first.
1013 __ lw(T0, Address(SP, 0 * kWordSize)); 1013 __ lw(T0, Address(SP, 0 * kWordSize));
1014 __ lw(T1, Address(SP, 1 * kWordSize)); 1014 __ lw(T1, Address(SP, 1 * kWordSize));
1015 __ beq(T0, T1, &true_label); 1015 __ beq(T0, T1, &true_label);
1016 1016
1017 __ or_(T2, T0, T1); 1017 __ or_(T2, T0, T1);
1018 __ andi(CMPRES, T2, Immediate(kSmiTagMask)); 1018 __ andi(CMPRES1, T2, Immediate(kSmiTagMask));
1019 // If T0 or T1 is not a smi do Mint checks. 1019 // If T0 or T1 is not a smi do Mint checks.
1020 __ bne(CMPRES, ZR, &check_for_mint); 1020 __ bne(CMPRES1, ZR, &check_for_mint);
1021 1021
1022 // Both arguments are smi, '===' is good enough. 1022 // Both arguments are smi, '===' is good enough.
1023 __ LoadObject(V0, Bool::False()); 1023 __ LoadObject(V0, Bool::False());
1024 __ Ret(); 1024 __ Ret();
1025 __ Bind(&true_label); 1025 __ Bind(&true_label);
1026 __ LoadObject(V0, Bool::True()); 1026 __ LoadObject(V0, Bool::True());
1027 __ Ret(); 1027 __ Ret();
1028 1028
1029 // At least one of the arguments was not Smi. 1029 // At least one of the arguments was not Smi.
1030 Label receiver_not_smi; 1030 Label receiver_not_smi;
1031 __ Bind(&check_for_mint); 1031 __ Bind(&check_for_mint);
1032 1032
1033 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); 1033 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
1034 __ bne(CMPRES, ZR, &receiver_not_smi); // Check receiver. 1034 __ bne(CMPRES1, ZR, &receiver_not_smi); // Check receiver.
1035 1035
1036 // Left (receiver) is Smi, return false if right is not Double. 1036 // Left (receiver) is Smi, return false if right is not Double.
1037 // Note that an instance of Mint or Bigint never contains a value that can be 1037 // Note that an instance of Mint or Bigint never contains a value that can be
1038 // represented by Smi. 1038 // represented by Smi.
1039 1039
1040 __ LoadClassId(CMPRES1, T0); 1040 __ LoadClassId(CMPRES1, T0);
1041 __ BranchEqual(CMPRES1, kDoubleCid, &fall_through); 1041 __ BranchEqual(CMPRES1, kDoubleCid, &fall_through);
1042 __ LoadObject(V0, Bool::False()); // Smi == Mint -> false. 1042 __ LoadObject(V0, Bool::False()); // Smi == Mint -> false.
1043 __ Ret(); 1043 __ Ret();
1044 1044
1045 __ Bind(&receiver_not_smi); 1045 __ Bind(&receiver_not_smi);
1046 // T1:: receiver. 1046 // T1:: receiver.
1047 1047
1048 __ LoadClassId(CMPRES1, T1); 1048 __ LoadClassId(CMPRES1, T1);
1049 __ BranchNotEqual(CMPRES1, kMintCid, &fall_through); 1049 __ BranchNotEqual(CMPRES1, kMintCid, &fall_through);
1050 // Receiver is Mint, return false if right is Smi. 1050 // Receiver is Mint, return false if right is Smi.
1051 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); 1051 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
1052 __ bne(CMPRES, ZR, &fall_through); 1052 __ bne(CMPRES1, ZR, &fall_through);
1053 __ LoadObject(V0, Bool::False()); 1053 __ LoadObject(V0, Bool::False());
1054 __ Ret(); 1054 __ Ret();
1055 // TODO(srdjan): Implement Mint == Mint comparison. 1055 // TODO(srdjan): Implement Mint == Mint comparison.
1056 1056
1057 __ Bind(&fall_through); 1057 __ Bind(&fall_through);
1058 } 1058 }
1059 1059
1060 1060
1061 void Intrinsifier::Integer_equal(Assembler* assembler) { 1061 void Intrinsifier::Integer_equal(Assembler* assembler) {
1062 return Integer_equalToInteger(assembler); 1062 return Integer_equalToInteger(assembler);
1063 } 1063 }
1064 1064
1065 1065
1066 void Intrinsifier::Integer_sar(Assembler* assembler) { 1066 void Intrinsifier::Integer_sar(Assembler* assembler) {
1067 Label fall_through; 1067 Label fall_through;
1068 1068
1069 TestBothArgumentsSmis(assembler, &fall_through); 1069 TestBothArgumentsSmis(assembler, &fall_through);
1070 // Shift amount in T0. Value to shift in T1. 1070 // Shift amount in T0. Value to shift in T1.
1071 1071
1072 __ SmiUntag(T0); 1072 __ SmiUntag(T0);
1073 __ bltz(T0, &fall_through); 1073 __ bltz(T0, &fall_through);
1074 1074
1075 __ LoadImmediate(T2, 0x1F); 1075 __ LoadImmediate(T2, 0x1F);
1076 __ slt(CMPRES, T2, T0); // CMPRES <- 0x1F < T0 ? 1 : 0 1076 __ slt(CMPRES1, T2, T0); // CMPRES1 <- 0x1F < T0 ? 1 : 0
1077 __ movn(T0, T2, CMPRES); // T0 <- 0x1F < T0 ? 0x1F : T0 1077 __ movn(T0, T2, CMPRES1); // T0 <- 0x1F < T0 ? 0x1F : T0
1078 1078
1079 __ SmiUntag(T1); 1079 __ SmiUntag(T1);
1080 __ srav(V0, T1, T0); 1080 __ srav(V0, T1, T0);
1081 __ Ret(); 1081 __ Ret();
1082 __ delay_slot()->SmiTag(V0); 1082 __ delay_slot()->SmiTag(V0);
1083 __ Bind(&fall_through); 1083 __ Bind(&fall_through);
1084 } 1084 }
1085 1085
1086 1086
1087 void Intrinsifier::Smi_bitNegate(Assembler* assembler) { 1087 void Intrinsifier::Smi_bitNegate(Assembler* assembler) {
1088 __ lw(T0, Address(SP, 0 * kWordSize)); 1088 __ lw(T0, Address(SP, 0 * kWordSize));
1089 __ nor(V0, T0, ZR); 1089 __ nor(V0, T0, ZR);
1090 __ Ret(); 1090 __ Ret();
1091 __ delay_slot()->addiu(V0, V0, Immediate(-1)); // Remove inverted smi-tag. 1091 __ delay_slot()->addiu(V0, V0, Immediate(-1)); // Remove inverted smi-tag.
1092 } 1092 }
1093 1093
1094 1094
1095 void Intrinsifier::Smi_bitLength(Assembler* assembler) { 1095 void Intrinsifier::Smi_bitLength(Assembler* assembler) {
1096 // TODO(sra): Implement. 1096 // TODO(sra): Implement.
1097 } 1097 }
1098 1098
1099 1099
1100 // Check if the last argument is a double, jump to label 'is_smi' if smi 1100 // Check if the last argument is a double, jump to label 'is_smi' if smi
1101 // (easy to convert to double), otherwise jump to label 'not_double_smi', 1101 // (easy to convert to double), otherwise jump to label 'not_double_smi',
1102 // Returns the last argument in T0. 1102 // Returns the last argument in T0.
1103 static void TestLastArgumentIsDouble(Assembler* assembler, 1103 static void TestLastArgumentIsDouble(Assembler* assembler,
1104 Label* is_smi, 1104 Label* is_smi,
1105 Label* not_double_smi) { 1105 Label* not_double_smi) {
1106 __ lw(T0, Address(SP, 0 * kWordSize)); 1106 __ lw(T0, Address(SP, 0 * kWordSize));
1107 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); 1107 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
1108 __ beq(CMPRES, ZR, is_smi); 1108 __ beq(CMPRES1, ZR, is_smi);
1109 __ LoadClassId(CMPRES1, T0); 1109 __ LoadClassId(CMPRES1, T0);
1110 __ BranchNotEqual(CMPRES1, kDoubleCid, not_double_smi); 1110 __ BranchNotEqual(CMPRES1, kDoubleCid, not_double_smi);
1111 // Fall through with Double in T0. 1111 // Fall through with Double in T0.
1112 } 1112 }
1113 1113
1114 1114
1115 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown 1115 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown
1116 // type. Return true or false object in the register V0. Any NaN argument 1116 // type. Return true or false object in the register V0. Any NaN argument
1117 // returns false. Any non-double arg1 causes control flow to fall through to the 1117 // returns false. Any non-double arg1 causes control flow to fall through to the
1118 // slow case (compiled method body). 1118 // slow case (compiled method body).
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 void Intrinsifier::Double_div(Assembler* assembler) { 1239 void Intrinsifier::Double_div(Assembler* assembler) {
1240 return DoubleArithmeticOperations(assembler, Token::kDIV); 1240 return DoubleArithmeticOperations(assembler, Token::kDIV);
1241 } 1241 }
1242 1242
1243 1243
1244 // Left is double right is integer (Bigint, Mint or Smi) 1244 // Left is double right is integer (Bigint, Mint or Smi)
1245 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) { 1245 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
1246 Label fall_through; 1246 Label fall_through;
1247 // Only smis allowed. 1247 // Only smis allowed.
1248 __ lw(T0, Address(SP, 0 * kWordSize)); 1248 __ lw(T0, Address(SP, 0 * kWordSize));
1249 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); 1249 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
1250 __ bne(CMPRES, ZR, &fall_through); 1250 __ bne(CMPRES1, ZR, &fall_through);
1251 1251
1252 // Is Smi. 1252 // Is Smi.
1253 __ SmiUntag(T0); 1253 __ SmiUntag(T0);
1254 __ mtc1(T0, F4); 1254 __ mtc1(T0, F4);
1255 __ cvtdw(D1, F4); 1255 __ cvtdw(D1, F4);
1256 1256
1257 __ lw(T0, Address(SP, 1 * kWordSize)); 1257 __ lw(T0, Address(SP, 1 * kWordSize));
1258 __ lwc1(F0, FieldAddress(T0, Double::value_offset())); 1258 __ lwc1(F0, FieldAddress(T0, Double::value_offset()));
1259 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); 1259 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize));
1260 __ muld(D0, D0, D1); 1260 __ muld(D0, D0, D1);
1261 const Class& double_class = Class::Handle( 1261 const Class& double_class = Class::Handle(
1262 Isolate::Current()->object_store()->double_class()); 1262 Isolate::Current()->object_store()->double_class());
1263 __ TryAllocate(double_class, &fall_through, V0); // Result register. 1263 __ TryAllocate(double_class, &fall_through, V0); // Result register.
1264 __ swc1(F0, FieldAddress(V0, Double::value_offset())); 1264 __ swc1(F0, FieldAddress(V0, Double::value_offset()));
1265 __ Ret(); 1265 __ Ret();
1266 __ delay_slot()->swc1(F1, 1266 __ delay_slot()->swc1(F1,
1267 FieldAddress(V0, Double::value_offset() + kWordSize)); 1267 FieldAddress(V0, Double::value_offset() + kWordSize));
1268 __ Bind(&fall_through); 1268 __ Bind(&fall_through);
1269 } 1269 }
1270 1270
1271 1271
1272 void Intrinsifier::Double_fromInteger(Assembler* assembler) { 1272 void Intrinsifier::Double_fromInteger(Assembler* assembler) {
1273 Label fall_through; 1273 Label fall_through;
1274 1274
1275 __ lw(T0, Address(SP, 0 * kWordSize)); 1275 __ lw(T0, Address(SP, 0 * kWordSize));
1276 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); 1276 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
1277 __ bne(T0, ZR, &fall_through); 1277 __ bne(T0, ZR, &fall_through);
1278 1278
1279 // Is Smi. 1279 // Is Smi.
1280 __ SmiUntag(T0); 1280 __ SmiUntag(T0);
1281 __ mtc1(T0, F4); 1281 __ mtc1(T0, F4);
1282 __ cvtdw(D0, F4); 1282 __ cvtdw(D0, F4);
1283 const Class& double_class = Class::Handle( 1283 const Class& double_class = Class::Handle(
1284 Isolate::Current()->object_store()->double_class()); 1284 Isolate::Current()->object_store()->double_class());
1285 __ TryAllocate(double_class, &fall_through, V0); // Result register. 1285 __ TryAllocate(double_class, &fall_through, V0); // Result register.
1286 __ swc1(F0, FieldAddress(V0, Double::value_offset())); 1286 __ swc1(F0, FieldAddress(V0, Double::value_offset()));
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 __ Ret(); 1327 __ Ret();
1328 1328
1329 __ Bind(&is_false); 1329 __ Bind(&is_false);
1330 __ LoadObject(V0, Bool::False()); 1330 __ LoadObject(V0, Bool::False());
1331 __ Ret(); 1331 __ Ret();
1332 1332
1333 __ Bind(&is_zero); 1333 __ Bind(&is_zero);
1334 // Check for negative zero by looking at the sign bit. 1334 // Check for negative zero by looking at the sign bit.
1335 __ mfc1(T0, F1); // Moves bits 32...63 of D0 to T0. 1335 __ mfc1(T0, F1); // Moves bits 32...63 of D0 to T0.
1336 __ srl(T0, T0, 31); // Get the sign bit down to bit 0 of T0. 1336 __ srl(T0, T0, 31); // Get the sign bit down to bit 0 of T0.
1337 __ andi(CMPRES, T0, Immediate(1)); // Check if the bit is set. 1337 __ andi(CMPRES1, T0, Immediate(1)); // Check if the bit is set.
1338 __ bne(T0, ZR, &is_true); // Sign bit set. True. 1338 __ bne(T0, ZR, &is_true); // Sign bit set. True.
1339 __ b(&is_false); 1339 __ b(&is_false);
1340 } 1340 }
1341 1341
1342 1342
1343 void Intrinsifier::Double_toInt(Assembler* assembler) { 1343 void Intrinsifier::Double_toInt(Assembler* assembler) {
1344 __ lw(T0, Address(SP, 0 * kWordSize)); 1344 __ lw(T0, Address(SP, 0 * kWordSize));
1345 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag); 1345 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag);
1346 1346
1347 __ cvtwd(F2, D0); 1347 __ cvtwd(F2, D0);
1348 __ mfc1(V0, F2); 1348 __ mfc1(V0, F2);
1349 1349
1350 // Overflow is signaled with minint. 1350 // Overflow is signaled with minint.
1351 Label fall_through; 1351 Label fall_through;
1352 // Check for overflow and that it fits into Smi. 1352 // Check for overflow and that it fits into Smi.
1353 __ LoadImmediate(TMP, 0xC0000000); 1353 __ LoadImmediate(TMP, 0xC0000000);
1354 __ subu(CMPRES, V0, TMP); 1354 __ subu(CMPRES1, V0, TMP);
1355 __ bltz(CMPRES, &fall_through); 1355 __ bltz(CMPRES1, &fall_through);
1356 __ Ret(); 1356 __ Ret();
1357 __ delay_slot()->SmiTag(V0); 1357 __ delay_slot()->SmiTag(V0);
1358 __ Bind(&fall_through); 1358 __ Bind(&fall_through);
1359 } 1359 }
1360 1360
1361 1361
1362 void Intrinsifier::Math_sqrt(Assembler* assembler) { 1362 void Intrinsifier::Math_sqrt(Assembler* assembler) {
1363 Label fall_through, is_smi, double_op; 1363 Label fall_through, is_smi, double_op;
1364 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1364 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1365 // Argument is double and is in T0. 1365 // Argument is double and is in T0.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1470 } 1470 }
1471 1471
1472 1472
1473 void Intrinsifier::String_codeUnitAt(Assembler* assembler) { 1473 void Intrinsifier::String_codeUnitAt(Assembler* assembler) {
1474 Label fall_through, try_two_byte_string; 1474 Label fall_through, try_two_byte_string;
1475 1475
1476 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. 1476 __ lw(T1, Address(SP, 0 * kWordSize)); // Index.
1477 __ lw(T0, Address(SP, 1 * kWordSize)); // String. 1477 __ lw(T0, Address(SP, 1 * kWordSize)); // String.
1478 1478
1479 // Checks. 1479 // Checks.
1480 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); 1480 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
1481 __ bne(T1, ZR, &fall_through); // Index is not a Smi. 1481 __ bne(T1, ZR, &fall_through); // Index is not a Smi.
1482 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. 1482 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check.
1483 // Runtime throws exception. 1483 // Runtime throws exception.
1484 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); 1484 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through);
1485 __ LoadClassId(CMPRES1, T0); // Class ID check. 1485 __ LoadClassId(CMPRES1, T0); // Class ID check.
1486 __ BranchNotEqual(CMPRES1, kOneByteStringCid, &try_two_byte_string); 1486 __ BranchNotEqual(CMPRES1, kOneByteStringCid, &try_two_byte_string);
1487 1487
1488 // Grab byte and return. 1488 // Grab byte and return.
1489 __ SmiUntag(T1); 1489 __ SmiUntag(T1);
1490 __ addu(T2, T0, T1); 1490 __ addu(T2, T0, T1);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1601 __ LoadImmediate(TMP, ~(kObjectAlignment - 1)); 1601 __ LoadImmediate(TMP, ~(kObjectAlignment - 1));
1602 __ and_(length_reg, length_reg, TMP); 1602 __ and_(length_reg, length_reg, TMP);
1603 1603
1604 Isolate* isolate = Isolate::Current(); 1604 Isolate* isolate = Isolate::Current();
1605 Heap* heap = isolate->heap(); 1605 Heap* heap = isolate->heap();
1606 1606
1607 __ LoadImmediate(T3, heap->TopAddress()); 1607 __ LoadImmediate(T3, heap->TopAddress());
1608 __ lw(V0, Address(T3, 0)); 1608 __ lw(V0, Address(T3, 0));
1609 1609
1610 // length_reg: allocation size. 1610 // length_reg: allocation size.
1611 __ AdduDetectOverflow(T1, V0, length_reg, CMPRES); 1611 __ AdduDetectOverflow(T1, V0, length_reg, CMPRES1);
1612 __ bltz(CMPRES, failure); // Fail on overflow. 1612 __ bltz(CMPRES1, failure); // Fail on overflow.
1613 1613
1614 // Check if the allocation fits into the remaining space. 1614 // Check if the allocation fits into the remaining space.
1615 // V0: potential new object start. 1615 // V0: potential new object start.
1616 // T1: potential next object start. 1616 // T1: potential next object start.
1617 // T2: allocation size. 1617 // T2: allocation size.
1618 // T3: heap->TopAddress(). 1618 // T3: heap->TopAddress().
1619 __ LoadImmediate(T4, heap->EndAddress()); 1619 __ LoadImmediate(T4, heap->EndAddress());
1620 __ lw(T4, Address(T4, 0)); 1620 __ lw(T4, Address(T4, 0));
1621 __ BranchUnsignedGreaterEqual(T1, T4, failure); 1621 __ BranchUnsignedGreaterEqual(T1, T4, failure);
1622 1622
(...skipping 14 matching lines...) Expand all
1637 1637
1638 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); 1638 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow);
1639 __ b(&done); 1639 __ b(&done);
1640 __ delay_slot()->sll(T2, T2, shift); 1640 __ delay_slot()->sll(T2, T2, shift);
1641 __ Bind(&overflow); 1641 __ Bind(&overflow);
1642 __ mov(T2, ZR); 1642 __ mov(T2, ZR);
1643 __ Bind(&done); 1643 __ Bind(&done);
1644 1644
1645 // Get the class index and insert it into the tags. 1645 // Get the class index and insert it into the tags.
1646 // T2: size and bit tags. 1646 // T2: size and bit tags.
1647 __ LoadImmediate(TMP1, RawObject::ClassIdTag::encode(cls.id())); 1647 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id()));
1648 __ or_(T2, T2, TMP1); 1648 __ or_(T2, T2, TMP);
1649 __ sw(T2, FieldAddress(V0, String::tags_offset())); // Store tags. 1649 __ sw(T2, FieldAddress(V0, String::tags_offset())); // Store tags.
1650 } 1650 }
1651 1651
1652 // Set the length field using the saved length (T6). 1652 // Set the length field using the saved length (T6).
1653 __ StoreIntoObjectNoBarrier(V0, 1653 __ StoreIntoObjectNoBarrier(V0,
1654 FieldAddress(V0, String::length_offset()), 1654 FieldAddress(V0, String::length_offset()),
1655 T6); 1655 T6);
1656 // Clear hash. 1656 // Clear hash.
1657 __ b(ok); 1657 __ b(ok);
1658 __ delay_slot()->sw(ZR, FieldAddress(V0, String::hash_offset())); 1658 __ delay_slot()->sw(ZR, FieldAddress(V0, String::hash_offset()));
1659 } 1659 }
1660 1660
1661 1661
1662 // Arg0: OneByteString (receiver). 1662 // Arg0: OneByteString (receiver).
1663 // Arg1: Start index as Smi. 1663 // Arg1: Start index as Smi.
1664 // Arg2: End index as Smi. 1664 // Arg2: End index as Smi.
1665 // The indexes must be valid. 1665 // The indexes must be valid.
1666 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { 1666 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) {
1667 const intptr_t kStringOffset = 2 * kWordSize; 1667 const intptr_t kStringOffset = 2 * kWordSize;
1668 const intptr_t kStartIndexOffset = 1 * kWordSize; 1668 const intptr_t kStartIndexOffset = 1 * kWordSize;
1669 const intptr_t kEndIndexOffset = 0 * kWordSize; 1669 const intptr_t kEndIndexOffset = 0 * kWordSize;
1670 Label fall_through, ok; 1670 Label fall_through, ok;
1671 1671
1672 __ lw(T2, Address(SP, kEndIndexOffset)); 1672 __ lw(T2, Address(SP, kEndIndexOffset));
1673 __ lw(TMP, Address(SP, kStartIndexOffset)); 1673 __ lw(TMP, Address(SP, kStartIndexOffset));
1674 __ or_(CMPRES, T2, TMP); 1674 __ or_(CMPRES1, T2, TMP);
1675 __ andi(CMPRES, CMPRES, Immediate(kSmiTagMask)); 1675 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask));
1676 __ bne(CMPRES, ZR, &fall_through); // 'start', 'end' not Smi. 1676 __ bne(CMPRES1, ZR, &fall_through); // 'start', 'end' not Smi.
1677 1677
1678 __ subu(T2, T2, TMP); 1678 __ subu(T2, T2, TMP);
1679 TryAllocateOnebyteString(assembler, &ok, &fall_through); 1679 TryAllocateOnebyteString(assembler, &ok, &fall_through);
1680 __ Bind(&ok); 1680 __ Bind(&ok);
1681 // V0: new string as tagged pointer. 1681 // V0: new string as tagged pointer.
1682 // Copy string. 1682 // Copy string.
1683 __ lw(T3, Address(SP, kStringOffset)); 1683 __ lw(T3, Address(SP, kStringOffset));
1684 __ lw(T1, Address(SP, kStartIndexOffset)); 1684 __ lw(T1, Address(SP, kStartIndexOffset));
1685 __ SmiUntag(T1); 1685 __ SmiUntag(T1);
1686 __ addu(T3, T3, T1); 1686 __ addu(T3, T3, T1);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1745 // TODO(srdjan): Add combinations (one-byte/two-byte/external strings). 1745 // TODO(srdjan): Add combinations (one-byte/two-byte/external strings).
1746 void StringEquality(Assembler* assembler, intptr_t string_cid) { 1746 void StringEquality(Assembler* assembler, intptr_t string_cid) {
1747 Label fall_through, is_true, is_false, loop; 1747 Label fall_through, is_true, is_false, loop;
1748 __ lw(T0, Address(SP, 1 * kWordSize)); // This. 1748 __ lw(T0, Address(SP, 1 * kWordSize)); // This.
1749 __ lw(T1, Address(SP, 0 * kWordSize)); // Other. 1749 __ lw(T1, Address(SP, 0 * kWordSize)); // Other.
1750 1750
1751 // Are identical? 1751 // Are identical?
1752 __ beq(T0, T1, &is_true); 1752 __ beq(T0, T1, &is_true);
1753 1753
1754 // Is other OneByteString? 1754 // Is other OneByteString?
1755 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); 1755 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
1756 __ beq(CMPRES, ZR, &fall_through); // Other is Smi. 1756 __ beq(CMPRES1, ZR, &fall_through); // Other is Smi.
1757 __ LoadClassId(CMPRES1, T1); // Class ID check. 1757 __ LoadClassId(CMPRES1, T1); // Class ID check.
1758 __ BranchNotEqual(CMPRES1, string_cid, &fall_through); 1758 __ BranchNotEqual(CMPRES1, string_cid, &fall_through);
1759 1759
1760 // Have same length? 1760 // Have same length?
1761 __ lw(T2, FieldAddress(T0, String::length_offset())); 1761 __ lw(T2, FieldAddress(T0, String::length_offset()));
1762 __ lw(T3, FieldAddress(T1, String::length_offset())); 1762 __ lw(T3, FieldAddress(T1, String::length_offset()));
1763 __ bne(T2, T3, &is_false); 1763 __ bne(T2, T3, &is_false);
1764 1764
1765 // Check contents, no fall-through possible. 1765 // Check contents, no fall-through possible.
1766 ASSERT((string_cid == kOneByteStringCid) || 1766 ASSERT((string_cid == kOneByteStringCid) ||
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1801 } 1801 }
1802 1802
1803 1803
1804 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { 1804 void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
1805 StringEquality(assembler, kTwoByteStringCid); 1805 StringEquality(assembler, kTwoByteStringCid);
1806 } 1806 }
1807 1807
1808 } // namespace dart 1808 } // namespace dart
1809 1809
1810 #endif // defined TARGET_ARCH_MIPS 1810 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698