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

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

Issue 593363003: Expands the use of Immediate and Operand wrappers. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 months 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
« no previous file with comments | « runtime/vm/intermediate_language_mips.cc ('k') | runtime/vm/intrinsifier_mips.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 __ CompareObject(R1, Object::null_object(), PP); 59 __ CompareObject(R1, Object::null_object(), PP);
60 __ b(&checked_ok, EQ); 60 __ b(&checked_ok, EQ);
61 61
62 // Check if it's dynamic. 62 // Check if it's dynamic.
63 // Get type at index 0. 63 // Get type at index 0.
64 __ ldr(R0, FieldAddress(R1, TypeArguments::type_at_offset(0))); 64 __ ldr(R0, FieldAddress(R1, TypeArguments::type_at_offset(0)));
65 __ CompareObject(R0, Type::ZoneHandle(Type::DynamicType()), PP); 65 __ CompareObject(R0, Type::ZoneHandle(Type::DynamicType()), PP);
66 __ b(&checked_ok, EQ); 66 __ b(&checked_ok, EQ);
67 67
68 // Check for int and num. 68 // Check for int and num.
69 __ tsti(R2, kSmiTagMask); // Value is Smi? 69 __ tsti(R2, Immediate(Immediate(kSmiTagMask))); // Value is Smi?
70 __ b(&fall_through, NE); // Non-smi value. 70 __ b(&fall_through, NE); // Non-smi value.
71 __ CompareObject(R0, Type::ZoneHandle(Type::IntType()), PP); 71 __ CompareObject(R0, Type::ZoneHandle(Type::IntType()), PP);
72 __ b(&checked_ok, EQ); 72 __ b(&checked_ok, EQ);
73 __ CompareObject(R0, Type::ZoneHandle(Type::Number()), PP); 73 __ CompareObject(R0, Type::ZoneHandle(Type::Number()), PP);
74 __ b(&fall_through, NE); 74 __ b(&fall_through, NE);
75 __ Bind(&checked_ok); 75 __ Bind(&checked_ok);
76 } 76 }
77 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index. 77 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index.
78 __ tsti(R1, kSmiTagMask); 78 __ tsti(R1, Immediate(kSmiTagMask));
79 // Index not Smi. 79 // Index not Smi.
80 __ b(&fall_through, NE); 80 __ b(&fall_through, NE);
81 __ ldr(R0, Address(SP, 2 * kWordSize)); // Array. 81 __ ldr(R0, Address(SP, 2 * kWordSize)); // Array.
82 82
83 // Range check. 83 // Range check.
84 __ ldr(R3, FieldAddress(R0, Array::length_offset())); // Array length. 84 __ ldr(R3, FieldAddress(R0, Array::length_offset())); // Array length.
85 __ cmp(R1, Operand(R3)); 85 __ cmp(R1, Operand(R3));
86 // Runtime throws exception. 86 // Runtime throws exception.
87 __ b(&fall_through, CS); 87 __ b(&fall_through, CS);
88 88
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 __ Bind(&fall_through); 136 __ Bind(&fall_through);
137 } 137 }
138 138
139 139
140 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) { 140 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
141 Label fall_through; 141 Label fall_through;
142 142
143 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index 143 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index
144 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array 144 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array
145 145
146 __ tsti(R0, kSmiTagMask); 146 __ tsti(R0, Immediate(kSmiTagMask));
147 __ b(&fall_through, NE); // Index is not an smi, fall through. 147 __ b(&fall_through, NE); // Index is not an smi, fall through.
148 148
149 // Range check. 149 // Range check.
150 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset())); 150 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset()));
151 __ cmp(R0, Operand(R6)); 151 __ cmp(R0, Operand(R6));
152 __ b(&fall_through, CS); 152 __ b(&fall_through, CS);
153 153
154 ASSERT(kSmiTagShift == 1); 154 ASSERT(kSmiTagShift == 1);
155 // array element at R6 + R0 * 4 + Array::data_offset - 1 155 // array element at R6 + R0 * 4 + Array::data_offset - 1
156 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset())); // Data 156 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset())); // Data
157 __ add(R6, R6, Operand(R0, LSL, 2)); 157 __ add(R6, R6, Operand(R0, LSL, 2));
158 __ ldr(R0, FieldAddress(R6, Array::data_offset())); 158 __ ldr(R0, FieldAddress(R6, Array::data_offset()));
159 __ ret(); 159 __ ret();
160 __ Bind(&fall_through); 160 __ Bind(&fall_through);
161 } 161 }
162 162
163 163
164 // Set value into growable object array at specified index. 164 // Set value into growable object array at specified index.
165 // On stack: growable array (+2), index (+1), value (+0). 165 // On stack: growable array (+2), index (+1), value (+0).
166 void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) { 166 void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
167 if (FLAG_enable_type_checks) { 167 if (FLAG_enable_type_checks) {
168 return; 168 return;
169 } 169 }
170 Label fall_through; 170 Label fall_through;
171 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index. 171 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index.
172 __ ldr(R0, Address(SP, 2 * kWordSize)); // GrowableArray. 172 __ ldr(R0, Address(SP, 2 * kWordSize)); // GrowableArray.
173 __ tsti(R1, kSmiTagMask); 173 __ tsti(R1, Immediate(kSmiTagMask));
174 __ b(&fall_through, NE); // Non-smi index. 174 __ b(&fall_through, NE); // Non-smi index.
175 // Range check using _length field. 175 // Range check using _length field.
176 __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset())); 176 __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset()));
177 __ cmp(R1, Operand(R2)); 177 __ cmp(R1, Operand(R2));
178 // Runtime throws exception. 178 // Runtime throws exception.
179 __ b(&fall_through, CS); 179 __ b(&fall_through, CS);
180 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); // data. 180 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); // data.
181 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. 181 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value.
182 // Note that R1 is Smi, i.e, times 2. 182 // Note that R1 is Smi, i.e, times 2.
183 ASSERT(kSmiTagShift == 1); 183 ASSERT(kSmiTagShift == 1);
184 __ add(R1, R0, Operand(R1, LSL, 2)); 184 __ add(R1, R0, Operand(R1, LSL, 2));
185 __ StoreIntoObject(R0, 185 __ StoreIntoObject(R0,
186 FieldAddress(R1, Array::data_offset()), 186 FieldAddress(R1, Array::data_offset()),
187 R2); 187 R2);
188 __ ret(); 188 __ ret();
189 __ Bind(&fall_through); 189 __ Bind(&fall_through);
190 } 190 }
191 191
192 192
193 // Set length of growable object array. The length cannot 193 // Set length of growable object array. The length cannot
194 // be greater than the length of the data container. 194 // be greater than the length of the data container.
195 // On stack: growable array (+1), length (+0). 195 // On stack: growable array (+1), length (+0).
196 void Intrinsifier::GrowableArraySetLength(Assembler* assembler) { 196 void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
197 Label fall_through; 197 Label fall_through;
198 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array. 198 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array.
199 __ ldr(R1, Address(SP, 0 * kWordSize)); // Length value. 199 __ ldr(R1, Address(SP, 0 * kWordSize)); // Length value.
200 __ tsti(R1, kSmiTagMask); // Check for Smi. 200 __ tsti(R1, Immediate(kSmiTagMask)); // Check for Smi.
201 __ b(&fall_through, NE); 201 __ b(&fall_through, NE);
202 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); 202 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
203 __ ret(); 203 __ ret();
204 __ Bind(&fall_through); 204 __ Bind(&fall_through);
205 // Fall through on non-Smi. 205 // Fall through on non-Smi.
206 } 206 }
207 207
208 208
209 // Set data of growable object array. 209 // Set data of growable object array.
210 // On stack: growable array (+1), data (+0). 210 // On stack: growable array (+1), data (+0).
211 void Intrinsifier::GrowableArraySetData(Assembler* assembler) { 211 void Intrinsifier::GrowableArraySetData(Assembler* assembler) {
212 if (FLAG_enable_type_checks) { 212 if (FLAG_enable_type_checks) {
213 return; 213 return;
214 } 214 }
215 Label fall_through; 215 Label fall_through;
216 __ ldr(R1, Address(SP, 0 * kWordSize)); // Data. 216 __ ldr(R1, Address(SP, 0 * kWordSize)); // Data.
217 // Check that data is an ObjectArray. 217 // Check that data is an ObjectArray.
218 __ tsti(R1, kSmiTagMask); 218 __ tsti(R1, Immediate(kSmiTagMask));
219 __ b(&fall_through, EQ); // Data is Smi. 219 __ b(&fall_through, EQ); // Data is Smi.
220 __ CompareClassId(R1, kArrayCid, kNoPP); 220 __ CompareClassId(R1, kArrayCid, kNoPP);
221 __ b(&fall_through, NE); 221 __ b(&fall_through, NE);
222 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array. 222 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array.
223 __ StoreIntoObject(R0, 223 __ StoreIntoObject(R0,
224 FieldAddress(R0, GrowableObjectArray::data_offset()), 224 FieldAddress(R0, GrowableObjectArray::data_offset()),
225 R1); 225 R1);
226 __ ret(); 226 __ ret();
227 __ Bind(&fall_through); 227 __ Bind(&fall_through);
228 } 228 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 return -1; 276 return -1;
277 } 277 }
278 278
279 279
280 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \ 280 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \
281 Label fall_through; \ 281 Label fall_through; \
282 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \ 282 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \
283 __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \ 283 __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \
284 /* Check that length is a positive Smi. */ \ 284 /* Check that length is a positive Smi. */ \
285 /* R2: requested array length argument. */ \ 285 /* R2: requested array length argument. */ \
286 __ tsti(R2, kSmiTagMask); \ 286 __ tsti(R2, Immediate(kSmiTagMask)); \
287 __ b(&fall_through, NE); \ 287 __ b(&fall_through, NE); \
288 __ CompareRegisters(R2, ZR); \ 288 __ CompareRegisters(R2, ZR); \
289 __ b(&fall_through, LT); \ 289 __ b(&fall_through, LT); \
290 __ SmiUntag(R2); \ 290 __ SmiUntag(R2); \
291 /* Check for maximum allowed length. */ \ 291 /* Check for maximum allowed length. */ \
292 /* R2: untagged array length. */ \ 292 /* R2: untagged array length. */ \
293 __ CompareImmediate(R2, max_len, kNoPP); \ 293 __ CompareImmediate(R2, max_len, kNoPP); \
294 __ b(&fall_through, GT); \ 294 __ b(&fall_through, GT); \
295 __ LslImmediate(R2, R2, scale_shift); \ 295 __ LslImmediate(R2, R2, scale_shift); \
296 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ 296 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \
297 __ AddImmediate(R2, R2, fixed_size, kNoPP); \ 297 __ AddImmediate(R2, R2, fixed_size, kNoPP); \
298 __ andi(R2, R2, ~(kObjectAlignment - 1)); \ 298 __ andi(R2, R2, Immediate(~(kObjectAlignment - 1))); \
299 Heap* heap = Isolate::Current()->heap(); \ 299 Heap* heap = Isolate::Current()->heap(); \
300 Heap::Space space = heap->SpaceForAllocation(cid); \ 300 Heap::Space space = heap->SpaceForAllocation(cid); \
301 __ LoadImmediate(R0, heap->TopAddress(space), kNoPP); \ 301 __ LoadImmediate(R0, heap->TopAddress(space), kNoPP); \
302 __ ldr(R0, Address(R0, 0)); \ 302 __ ldr(R0, Address(R0, 0)); \
303 \ 303 \
304 /* R2: allocation size. */ \ 304 /* R2: allocation size. */ \
305 __ add(R1, R0, Operand(R2)); \ 305 __ add(R1, R0, Operand(R2)); \
306 __ b(&fall_through, VS); \ 306 __ b(&fall_through, VS); \
307 \ 307 \
308 /* Check if the allocation fits into the remaining space. */ \ 308 /* Check if the allocation fits into the remaining space. */ \
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR) 378 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
379 #undef TYPED_DATA_ALLOCATOR 379 #undef TYPED_DATA_ALLOCATOR
380 380
381 381
382 // Loads args from stack into R0 and R1 382 // Loads args from stack into R0 and R1
383 // Tests if they are smis, jumps to label not_smi if not. 383 // Tests if they are smis, jumps to label not_smi if not.
384 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { 384 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
385 __ ldr(R0, Address(SP, + 0 * kWordSize)); 385 __ ldr(R0, Address(SP, + 0 * kWordSize));
386 __ ldr(R1, Address(SP, + 1 * kWordSize)); 386 __ ldr(R1, Address(SP, + 1 * kWordSize));
387 __ orr(TMP, R0, Operand(R1)); 387 __ orr(TMP, R0, Operand(R1));
388 __ tsti(TMP, kSmiTagMask); 388 __ tsti(TMP, Immediate(kSmiTagMask));
389 __ b(not_smi, NE); 389 __ b(not_smi, NE);
390 } 390 }
391 391
392 392
393 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) { 393 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
394 Label fall_through; 394 Label fall_through;
395 TestBothArgumentsSmis(assembler, &fall_through); // Checks two smis. 395 TestBothArgumentsSmis(assembler, &fall_through); // Checks two smis.
396 __ adds(R0, R0, Operand(R1)); // Adds. 396 __ adds(R0, R0, Operand(R1)); // Adds.
397 __ b(&fall_through, VS); // Fall-through on overflow. 397 __ b(&fall_through, VS); // Fall-through on overflow.
398 __ ret(); 398 __ ret();
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 // } else { 503 // } else {
504 // res = res + right; 504 // res = res + right;
505 // } 505 // }
506 // } 506 // }
507 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) { 507 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) {
508 // Check to see if we have integer division 508 // Check to see if we have integer division
509 Label neg_remainder, fall_through; 509 Label neg_remainder, fall_through;
510 __ ldr(R1, Address(SP, + 0 * kWordSize)); 510 __ ldr(R1, Address(SP, + 0 * kWordSize));
511 __ ldr(R0, Address(SP, + 1 * kWordSize)); 511 __ ldr(R0, Address(SP, + 1 * kWordSize));
512 __ orr(TMP, R0, Operand(R1)); 512 __ orr(TMP, R0, Operand(R1));
513 __ tsti(TMP, kSmiTagMask); 513 __ tsti(TMP, Immediate(kSmiTagMask));
514 __ b(&fall_through, NE); 514 __ b(&fall_through, NE);
515 // R1: Tagged left (dividend). 515 // R1: Tagged left (dividend).
516 // R0: Tagged right (divisor). 516 // R0: Tagged right (divisor).
517 // Check if modulo by zero -> exception thrown in main function. 517 // Check if modulo by zero -> exception thrown in main function.
518 __ CompareRegisters(R0, ZR); 518 __ CompareRegisters(R0, ZR);
519 __ b(&fall_through, EQ); 519 __ b(&fall_through, EQ);
520 EmitRemainderOperation(assembler); 520 EmitRemainderOperation(assembler);
521 // Untagged right in R0. Untagged remainder result in R1. 521 // Untagged right in R0. Untagged remainder result in R1.
522 522
523 __ CompareRegisters(R1, ZR); 523 __ CompareRegisters(R1, ZR);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 __ b(&fall_through, EQ); 557 __ b(&fall_through, EQ);
558 __ SmiTag(R0); // Not equal. Okay to tag and return. 558 __ SmiTag(R0); // Not equal. Okay to tag and return.
559 __ ret(); // Return. 559 __ ret(); // Return.
560 __ Bind(&fall_through); 560 __ Bind(&fall_through);
561 } 561 }
562 562
563 563
564 void Intrinsifier::Integer_negate(Assembler* assembler) { 564 void Intrinsifier::Integer_negate(Assembler* assembler) {
565 Label fall_through; 565 Label fall_through;
566 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Grab first argument. 566 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Grab first argument.
567 __ tsti(R0, kSmiTagMask); // Test for Smi. 567 __ tsti(R0, Immediate(kSmiTagMask)); // Test for Smi.
568 __ b(&fall_through, NE); 568 __ b(&fall_through, NE);
569 __ negs(R0, R0); 569 __ negs(R0, R0);
570 __ b(&fall_through, VS); 570 __ b(&fall_through, VS);
571 __ ret(); 571 __ ret();
572 __ Bind(&fall_through); 572 __ Bind(&fall_through);
573 } 573 }
574 574
575 575
576 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) { 576 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
577 Label fall_through; 577 Label fall_through;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 // can be Smi, Mint, Bigint or double. 687 // can be Smi, Mint, Bigint or double.
688 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) { 688 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
689 Label fall_through, true_label, check_for_mint; 689 Label fall_through, true_label, check_for_mint;
690 // For integer receiver '===' check first. 690 // For integer receiver '===' check first.
691 __ ldr(R0, Address(SP, 0 * kWordSize)); 691 __ ldr(R0, Address(SP, 0 * kWordSize));
692 __ ldr(R1, Address(SP, 1 * kWordSize)); 692 __ ldr(R1, Address(SP, 1 * kWordSize));
693 __ cmp(R0, Operand(R1)); 693 __ cmp(R0, Operand(R1));
694 __ b(&true_label, EQ); 694 __ b(&true_label, EQ);
695 695
696 __ orr(R2, R0, Operand(R1)); 696 __ orr(R2, R0, Operand(R1));
697 __ tsti(R2, kSmiTagMask); 697 __ tsti(R2, Immediate(kSmiTagMask));
698 __ b(&check_for_mint, NE); // If R0 or R1 is not a smi do Mint checks. 698 __ b(&check_for_mint, NE); // If R0 or R1 is not a smi do Mint checks.
699 699
700 // Both arguments are smi, '===' is good enough. 700 // Both arguments are smi, '===' is good enough.
701 __ LoadObject(R0, Bool::False(), PP); 701 __ LoadObject(R0, Bool::False(), PP);
702 __ ret(); 702 __ ret();
703 __ Bind(&true_label); 703 __ Bind(&true_label);
704 __ LoadObject(R0, Bool::True(), PP); 704 __ LoadObject(R0, Bool::True(), PP);
705 __ ret(); 705 __ ret();
706 706
707 // At least one of the arguments was not Smi. 707 // At least one of the arguments was not Smi.
708 Label receiver_not_smi; 708 Label receiver_not_smi;
709 __ Bind(&check_for_mint); 709 __ Bind(&check_for_mint);
710 710
711 __ tsti(R1, kSmiTagMask); // Check receiver. 711 __ tsti(R1, Immediate(kSmiTagMask)); // Check receiver.
712 __ b(&receiver_not_smi, NE); 712 __ b(&receiver_not_smi, NE);
713 713
714 // Left (receiver) is Smi, return false if right is not Double. 714 // Left (receiver) is Smi, return false if right is not Double.
715 // Note that an instance of Mint or Bigint never contains a value that can be 715 // Note that an instance of Mint or Bigint never contains a value that can be
716 // represented by Smi. 716 // represented by Smi.
717 717
718 __ CompareClassId(R0, kDoubleCid, kNoPP); 718 __ CompareClassId(R0, kDoubleCid, kNoPP);
719 __ b(&fall_through, EQ); 719 __ b(&fall_through, EQ);
720 __ LoadObject(R0, Bool::False(), PP); // Smi == Mint -> false. 720 __ LoadObject(R0, Bool::False(), PP); // Smi == Mint -> false.
721 __ ret(); 721 __ ret();
722 722
723 __ Bind(&receiver_not_smi); 723 __ Bind(&receiver_not_smi);
724 // R1: receiver. 724 // R1: receiver.
725 725
726 __ CompareClassId(R1, kMintCid, kNoPP); 726 __ CompareClassId(R1, kMintCid, kNoPP);
727 __ b(&fall_through, NE); 727 __ b(&fall_through, NE);
728 // Receiver is Mint, return false if right is Smi. 728 // Receiver is Mint, return false if right is Smi.
729 __ tsti(R0, kSmiTagMask); 729 __ tsti(R0, Immediate(kSmiTagMask));
730 __ b(&fall_through, NE); 730 __ b(&fall_through, NE);
731 __ LoadObject(R0, Bool::False(), PP); 731 __ LoadObject(R0, Bool::False(), PP);
732 __ ret(); 732 __ ret();
733 // TODO(srdjan): Implement Mint == Mint comparison. 733 // TODO(srdjan): Implement Mint == Mint comparison.
734 734
735 __ Bind(&fall_through); 735 __ Bind(&fall_through);
736 } 736 }
737 737
738 738
739 void Intrinsifier::Integer_equal(Assembler* assembler) { 739 void Intrinsifier::Integer_equal(Assembler* assembler) {
(...skipping 20 matching lines...) Expand all
760 __ asrv(R0, R1, R0); 760 __ asrv(R0, R1, R0);
761 __ SmiTag(R0); 761 __ SmiTag(R0);
762 __ ret(); 762 __ ret();
763 __ Bind(&fall_through); 763 __ Bind(&fall_through);
764 } 764 }
765 765
766 766
767 void Intrinsifier::Smi_bitNegate(Assembler* assembler) { 767 void Intrinsifier::Smi_bitNegate(Assembler* assembler) {
768 __ ldr(R0, Address(SP, 0 * kWordSize)); 768 __ ldr(R0, Address(SP, 0 * kWordSize));
769 __ mvn(R0, R0); 769 __ mvn(R0, R0);
770 __ andi(R0, R0, ~kSmiTagMask); // Remove inverted smi-tag. 770 __ andi(R0, R0, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
771 __ ret(); 771 __ ret();
772 } 772 }
773 773
774 774
775 void Intrinsifier::Smi_bitLength(Assembler* assembler) { 775 void Intrinsifier::Smi_bitLength(Assembler* assembler) {
776 // TODO(sra): Implement as word-length - CLZ. 776 // TODO(sra): Implement as word-length - CLZ.
777 } 777 }
778 778
779 779
780 void Intrinsifier::Bigint_setNeg(Assembler* assembler) { 780 void Intrinsifier::Bigint_setNeg(Assembler* assembler) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
831 } 831 }
832 832
833 833
834 // Check if the last argument is a double, jump to label 'is_smi' if smi 834 // Check if the last argument is a double, jump to label 'is_smi' if smi
835 // (easy to convert to double), otherwise jump to label 'not_double_smi', 835 // (easy to convert to double), otherwise jump to label 'not_double_smi',
836 // Returns the last argument in R0. 836 // Returns the last argument in R0.
837 static void TestLastArgumentIsDouble(Assembler* assembler, 837 static void TestLastArgumentIsDouble(Assembler* assembler,
838 Label* is_smi, 838 Label* is_smi,
839 Label* not_double_smi) { 839 Label* not_double_smi) {
840 __ ldr(R0, Address(SP, 0 * kWordSize)); 840 __ ldr(R0, Address(SP, 0 * kWordSize));
841 __ tsti(R0, kSmiTagMask); 841 __ tsti(R0, Immediate(kSmiTagMask));
842 __ b(is_smi, EQ); 842 __ b(is_smi, EQ);
843 __ CompareClassId(R0, kDoubleCid, kNoPP); 843 __ CompareClassId(R0, kDoubleCid, kNoPP);
844 __ b(not_double_smi, NE); 844 __ b(not_double_smi, NE);
845 // Fall through with Double in R0. 845 // Fall through with Double in R0.
846 } 846 }
847 847
848 848
849 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown 849 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown
850 // type. Return true or false object in the register R0. Any NaN argument 850 // type. Return true or false object in the register R0. Any NaN argument
851 // returns false. Any non-double arg1 causes control flow to fall through to the 851 // returns false. Any non-double arg1 causes control flow to fall through to the
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
948 void Intrinsifier::Double_div(Assembler* assembler) { 948 void Intrinsifier::Double_div(Assembler* assembler) {
949 DoubleArithmeticOperations(assembler, Token::kDIV); 949 DoubleArithmeticOperations(assembler, Token::kDIV);
950 } 950 }
951 951
952 952
953 // Left is double right is integer (Bigint, Mint or Smi) 953 // Left is double right is integer (Bigint, Mint or Smi)
954 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) { 954 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
955 Label fall_through; 955 Label fall_through;
956 // Only smis allowed. 956 // Only smis allowed.
957 __ ldr(R0, Address(SP, 0 * kWordSize)); 957 __ ldr(R0, Address(SP, 0 * kWordSize));
958 __ tsti(R0, kSmiTagMask); 958 __ tsti(R0, Immediate(kSmiTagMask));
959 __ b(&fall_through, NE); 959 __ b(&fall_through, NE);
960 // Is Smi. 960 // Is Smi.
961 __ SmiUntag(R0); 961 __ SmiUntag(R0);
962 __ scvtfd(V1, R0); 962 __ scvtfd(V1, R0);
963 __ ldr(R0, Address(SP, 1 * kWordSize)); 963 __ ldr(R0, Address(SP, 1 * kWordSize));
964 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); 964 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
965 __ fmuld(V0, V0, V1); 965 __ fmuld(V0, V0, V1);
966 const Class& double_class = Class::Handle( 966 const Class& double_class = Class::Handle(
967 Isolate::Current()->object_store()->double_class()); 967 Isolate::Current()->object_store()->double_class());
968 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP); 968 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
969 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); 969 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
970 __ ret(); 970 __ ret();
971 __ Bind(&fall_through); 971 __ Bind(&fall_through);
972 } 972 }
973 973
974 974
975 void Intrinsifier::DoubleFromInteger(Assembler* assembler) { 975 void Intrinsifier::DoubleFromInteger(Assembler* assembler) {
976 Label fall_through; 976 Label fall_through;
977 977
978 __ ldr(R0, Address(SP, 0 * kWordSize)); 978 __ ldr(R0, Address(SP, 0 * kWordSize));
979 __ tsti(R0, kSmiTagMask); 979 __ tsti(R0, Immediate(kSmiTagMask));
980 __ b(&fall_through, NE); 980 __ b(&fall_through, NE);
981 // Is Smi. 981 // Is Smi.
982 __ SmiUntag(R0); 982 __ SmiUntag(R0);
983 __ scvtfd(V0, R0); 983 __ scvtfd(V0, R0);
984 const Class& double_class = Class::Handle( 984 const Class& double_class = Class::Handle(
985 Isolate::Current()->object_store()->double_class()); 985 Isolate::Current()->object_store()->double_class());
986 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP); 986 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
987 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); 987 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
988 __ ret(); 988 __ ret();
989 __ Bind(&fall_through); 989 __ Bind(&fall_through);
(...skipping 29 matching lines...) Expand all
1019 __ Bind(&is_true); 1019 __ Bind(&is_true);
1020 __ mov(R0, true_reg); 1020 __ mov(R0, true_reg);
1021 1021
1022 __ Bind(&is_false); 1022 __ Bind(&is_false);
1023 __ ret(); 1023 __ ret();
1024 1024
1025 __ Bind(&is_zero); 1025 __ Bind(&is_zero);
1026 // Check for negative zero by looking at the sign bit. 1026 // Check for negative zero by looking at the sign bit.
1027 __ fmovrd(R1, V0); 1027 __ fmovrd(R1, V0);
1028 __ LsrImmediate(R1, R1, 63); 1028 __ LsrImmediate(R1, R1, 63);
1029 __ tsti(R1, 1); 1029 __ tsti(R1, Immediate(1));
1030 __ csel(R0, true_reg, false_reg, NE); // Sign bit set. 1030 __ csel(R0, true_reg, false_reg, NE); // Sign bit set.
1031 __ ret(); 1031 __ ret();
1032 } 1032 }
1033 1033
1034 1034
1035 void Intrinsifier::DoubleToInteger(Assembler* assembler) { 1035 void Intrinsifier::DoubleToInteger(Assembler* assembler) {
1036 Label fall_through; 1036 Label fall_through;
1037 1037
1038 __ ldr(R0, Address(SP, 0 * kWordSize)); 1038 __ ldr(R0, Address(SP, 0 * kWordSize));
1039 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); 1039 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 __ ldr(R0, Address(SP, 0 * kWordSize)); // Receiver. 1096 __ ldr(R0, Address(SP, 0 * kWordSize)); // Receiver.
1097 __ ldr(R1, FieldAddress(R0, state_field.Offset())); // Field '_state'. 1097 __ ldr(R1, FieldAddress(R0, state_field.Offset())); // Field '_state'.
1098 1098
1099 // Addresses of _state[0]. 1099 // Addresses of _state[0].
1100 const int64_t disp = 1100 const int64_t disp =
1101 Instance::DataOffsetFor(kTypedDataUint32ArrayCid) - kHeapObjectTag; 1101 Instance::DataOffsetFor(kTypedDataUint32ArrayCid) - kHeapObjectTag;
1102 1102
1103 __ LoadImmediate(R0, a_int_value, kNoPP); 1103 __ LoadImmediate(R0, a_int_value, kNoPP);
1104 __ LoadFromOffset(R2, R1, disp, kNoPP); 1104 __ LoadFromOffset(R2, R1, disp, kNoPP);
1105 __ LsrImmediate(R3, R2, 32); 1105 __ LsrImmediate(R3, R2, 32);
1106 __ andi(R2, R2, 0xffffffff); 1106 __ andi(R2, R2, Immediate(0xffffffff));
1107 __ mul(R2, R0, R2); 1107 __ mul(R2, R0, R2);
1108 __ add(R2, R2, Operand(R3)); 1108 __ add(R2, R2, Operand(R3));
1109 __ StoreToOffset(R2, R1, disp, kNoPP); 1109 __ StoreToOffset(R2, R1, disp, kNoPP);
1110 __ ret(); 1110 __ ret();
1111 } 1111 }
1112 1112
1113 1113
1114 void Intrinsifier::ObjectEquals(Assembler* assembler) { 1114 void Intrinsifier::ObjectEquals(Assembler* assembler) {
1115 __ ldr(R0, Address(SP, 0 * kWordSize)); 1115 __ ldr(R0, Address(SP, 0 * kWordSize));
1116 __ ldr(R1, Address(SP, 1 * kWordSize)); 1116 __ ldr(R1, Address(SP, 1 * kWordSize));
(...skipping 15 matching lines...) Expand all
1132 // Hash not yet computed. 1132 // Hash not yet computed.
1133 __ Bind(&fall_through); 1133 __ Bind(&fall_through);
1134 } 1134 }
1135 1135
1136 1136
1137 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { 1137 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) {
1138 Label fall_through, try_two_byte_string; 1138 Label fall_through, try_two_byte_string;
1139 1139
1140 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. 1140 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index.
1141 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. 1141 __ ldr(R0, Address(SP, 1 * kWordSize)); // String.
1142 __ tsti(R1, kSmiTagMask); 1142 __ tsti(R1, Immediate(kSmiTagMask));
1143 __ b(&fall_through, NE); // Index is not a Smi. 1143 __ b(&fall_through, NE); // Index is not a Smi.
1144 // Range check. 1144 // Range check.
1145 __ ldr(R2, FieldAddress(R0, String::length_offset())); 1145 __ ldr(R2, FieldAddress(R0, String::length_offset()));
1146 __ cmp(R1, Operand(R2)); 1146 __ cmp(R1, Operand(R2));
1147 __ b(&fall_through, CS); // Runtime throws exception. 1147 __ b(&fall_through, CS); // Runtime throws exception.
1148 __ CompareClassId(R0, kOneByteStringCid, kNoPP); 1148 __ CompareClassId(R0, kOneByteStringCid, kNoPP);
1149 __ b(&try_two_byte_string, NE); 1149 __ b(&try_two_byte_string, NE);
1150 __ SmiUntag(R1); 1150 __ SmiUntag(R1);
1151 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP); 1151 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP);
1152 __ ldr(R0, Address(R0, R1), kUnsignedByte); 1152 __ ldr(R0, Address(R0, R1), kUnsignedByte);
(...skipping 11 matching lines...) Expand all
1164 1164
1165 __ Bind(&fall_through); 1165 __ Bind(&fall_through);
1166 } 1166 }
1167 1167
1168 1168
1169 void Intrinsifier::StringBaseCharAt(Assembler* assembler) { 1169 void Intrinsifier::StringBaseCharAt(Assembler* assembler) {
1170 Label fall_through, try_two_byte_string; 1170 Label fall_through, try_two_byte_string;
1171 1171
1172 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. 1172 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index.
1173 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. 1173 __ ldr(R0, Address(SP, 1 * kWordSize)); // String.
1174 __ tsti(R1, kSmiTagMask); 1174 __ tsti(R1, Immediate(kSmiTagMask));
1175 __ b(&fall_through, NE); // Index is not a Smi. 1175 __ b(&fall_through, NE); // Index is not a Smi.
1176 // Range check. 1176 // Range check.
1177 __ ldr(R2, FieldAddress(R0, String::length_offset())); 1177 __ ldr(R2, FieldAddress(R0, String::length_offset()));
1178 __ cmp(R1, Operand(R2)); 1178 __ cmp(R1, Operand(R2));
1179 __ b(&fall_through, CS); // Runtime throws exception. 1179 __ b(&fall_through, CS); // Runtime throws exception.
1180 1180
1181 __ CompareClassId(R0, kOneByteStringCid, kNoPP); 1181 __ CompareClassId(R0, kOneByteStringCid, kNoPP);
1182 __ b(&try_two_byte_string, NE); 1182 __ b(&try_two_byte_string, NE);
1183 __ SmiUntag(R1); 1183 __ SmiUntag(R1);
1184 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP); 1184 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1290 static void TryAllocateOnebyteString(Assembler* assembler, 1290 static void TryAllocateOnebyteString(Assembler* assembler,
1291 Label* ok, 1291 Label* ok,
1292 Label* failure) { 1292 Label* failure) {
1293 const Register length_reg = R2; 1293 const Register length_reg = R2;
1294 Label fail; 1294 Label fail;
1295 1295
1296 __ mov(R6, length_reg); // Save the length register. 1296 __ mov(R6, length_reg); // Save the length register.
1297 __ SmiUntag(length_reg); 1297 __ SmiUntag(length_reg);
1298 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; 1298 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1;
1299 __ AddImmediate(length_reg, length_reg, fixed_size, kNoPP); 1299 __ AddImmediate(length_reg, length_reg, fixed_size, kNoPP);
1300 __ andi(length_reg, length_reg, ~(kObjectAlignment - 1)); 1300 __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1)));
1301 1301
1302 Isolate* isolate = Isolate::Current(); 1302 Isolate* isolate = Isolate::Current();
1303 Heap* heap = isolate->heap(); 1303 Heap* heap = isolate->heap();
1304 const intptr_t cid = kOneByteStringCid; 1304 const intptr_t cid = kOneByteStringCid;
1305 Heap::Space space = heap->SpaceForAllocation(cid); 1305 Heap::Space space = heap->SpaceForAllocation(cid);
1306 __ LoadImmediate(R3, heap->TopAddress(space), kNoPP); 1306 __ LoadImmediate(R3, heap->TopAddress(space), kNoPP);
1307 __ ldr(R0, Address(R3)); 1307 __ ldr(R0, Address(R3));
1308 1308
1309 // length_reg: allocation size. 1309 // length_reg: allocation size.
1310 __ adds(R1, R0, Operand(length_reg)); 1310 __ adds(R1, R0, Operand(length_reg));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 // The indexes must be valid. 1364 // The indexes must be valid.
1365 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { 1365 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) {
1366 const intptr_t kStringOffset = 2 * kWordSize; 1366 const intptr_t kStringOffset = 2 * kWordSize;
1367 const intptr_t kStartIndexOffset = 1 * kWordSize; 1367 const intptr_t kStartIndexOffset = 1 * kWordSize;
1368 const intptr_t kEndIndexOffset = 0 * kWordSize; 1368 const intptr_t kEndIndexOffset = 0 * kWordSize;
1369 Label fall_through, ok; 1369 Label fall_through, ok;
1370 1370
1371 __ ldr(R2, Address(SP, kEndIndexOffset)); 1371 __ ldr(R2, Address(SP, kEndIndexOffset));
1372 __ ldr(TMP, Address(SP, kStartIndexOffset)); 1372 __ ldr(TMP, Address(SP, kStartIndexOffset));
1373 __ orr(R3, R2, Operand(TMP)); 1373 __ orr(R3, R2, Operand(TMP));
1374 __ tsti(R3, kSmiTagMask); 1374 __ tsti(R3, Immediate(kSmiTagMask));
1375 __ b(&fall_through, NE); // 'start', 'end' not Smi. 1375 __ b(&fall_through, NE); // 'start', 'end' not Smi.
1376 1376
1377 __ sub(R2, R2, Operand(TMP)); 1377 __ sub(R2, R2, Operand(TMP));
1378 TryAllocateOnebyteString(assembler, &ok, &fall_through); 1378 TryAllocateOnebyteString(assembler, &ok, &fall_through);
1379 __ Bind(&ok); 1379 __ Bind(&ok);
1380 // R0: new string as tagged pointer. 1380 // R0: new string as tagged pointer.
1381 // Copy string. 1381 // Copy string.
1382 __ ldr(R3, Address(SP, kStringOffset)); 1382 __ ldr(R3, Address(SP, kStringOffset));
1383 __ ldr(R1, Address(SP, kStartIndexOffset)); 1383 __ ldr(R1, Address(SP, kStartIndexOffset));
1384 __ SmiUntag(R1); 1384 __ SmiUntag(R1);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 void StringEquality(Assembler* assembler, intptr_t string_cid) { 1447 void StringEquality(Assembler* assembler, intptr_t string_cid) {
1448 Label fall_through, is_true, is_false, loop; 1448 Label fall_through, is_true, is_false, loop;
1449 __ ldr(R0, Address(SP, 1 * kWordSize)); // This. 1449 __ ldr(R0, Address(SP, 1 * kWordSize)); // This.
1450 __ ldr(R1, Address(SP, 0 * kWordSize)); // Other. 1450 __ ldr(R1, Address(SP, 0 * kWordSize)); // Other.
1451 1451
1452 // Are identical? 1452 // Are identical?
1453 __ cmp(R0, Operand(R1)); 1453 __ cmp(R0, Operand(R1));
1454 __ b(&is_true, EQ); 1454 __ b(&is_true, EQ);
1455 1455
1456 // Is other OneByteString? 1456 // Is other OneByteString?
1457 __ tsti(R1, kSmiTagMask); 1457 __ tsti(R1, Immediate(kSmiTagMask));
1458 __ b(&fall_through, EQ); 1458 __ b(&fall_through, EQ);
1459 __ CompareClassId(R1, string_cid, kNoPP); 1459 __ CompareClassId(R1, string_cid, kNoPP);
1460 __ b(&fall_through, NE); 1460 __ b(&fall_through, NE);
1461 1461
1462 // Have same length? 1462 // Have same length?
1463 __ ldr(R2, FieldAddress(R0, String::length_offset())); 1463 __ ldr(R2, FieldAddress(R0, String::length_offset()));
1464 __ ldr(R3, FieldAddress(R1, String::length_offset())); 1464 __ ldr(R3, FieldAddress(R1, String::length_offset()));
1465 __ cmp(R2, Operand(R3)); 1465 __ cmp(R2, Operand(R3));
1466 __ b(&is_false, NE); 1466 __ b(&is_false, NE);
1467 1467
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1552 Isolate* isolate = Isolate::Current(); 1552 Isolate* isolate = Isolate::Current();
1553 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP); 1553 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP);
1554 // Set return value to Isolate::current_tag_. 1554 // Set return value to Isolate::current_tag_.
1555 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); 1555 __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
1556 __ ret(); 1556 __ ret();
1557 } 1557 }
1558 1558
1559 } // namespace dart 1559 } // namespace dart
1560 1560
1561 #endif // defined TARGET_ARCH_ARM64 1561 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_mips.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698