| OLD | NEW |
| 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 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 /* R2: requested array length argument. */ \ | 285 /* R2: requested array length argument. */ \ |
| 286 __ tsti(R2, kSmiTagMask); \ | 286 __ tsti(R2, 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 __ Lsl(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, ~(kObjectAlignment - 1)); \ |
| 299 Heap* heap = Isolate::Current()->heap(); \ | 299 Heap* heap = Isolate::Current()->heap(); \ |
| 300 \ | 300 \ |
| 301 __ LoadImmediate(R0, heap->TopAddress(), kNoPP); \ | 301 __ LoadImmediate(R0, heap->TopAddress(), 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)); \ |
| (...skipping 13 matching lines...) Expand all Loading... |
| 319 __ LoadImmediate(R3, heap->TopAddress(), kNoPP); \ | 319 __ LoadImmediate(R3, heap->TopAddress(), kNoPP); \ |
| 320 __ str(R1, Address(R3, 0)); \ | 320 __ str(R1, Address(R3, 0)); \ |
| 321 __ AddImmediate(R0, R0, kHeapObjectTag, kNoPP); \ | 321 __ AddImmediate(R0, R0, kHeapObjectTag, kNoPP); \ |
| 322 __ UpdateAllocationStatsWithSize(cid, R2, kNoPP); \ | 322 __ UpdateAllocationStatsWithSize(cid, R2, kNoPP); \ |
| 323 /* Initialize the tags. */ \ | 323 /* Initialize the tags. */ \ |
| 324 /* R0: new object start as a tagged pointer. */ \ | 324 /* R0: new object start as a tagged pointer. */ \ |
| 325 /* R1: new object end address. */ \ | 325 /* R1: new object end address. */ \ |
| 326 /* R2: allocation size. */ \ | 326 /* R2: allocation size. */ \ |
| 327 { \ | 327 { \ |
| 328 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP); \ | 328 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP); \ |
| 329 __ Lsl(R2, R2, RawObject::kSizeTagPos - kObjectAlignmentLog2); \ | 329 __ LslImmediate(R2, R2, RawObject::kSizeTagPos - kObjectAlignmentLog2); \ |
| 330 __ csel(R2, ZR, R2, HI); \ | 330 __ csel(R2, ZR, R2, HI); \ |
| 331 \ | 331 \ |
| 332 /* Get the class index and insert it into the tags. */ \ | 332 /* Get the class index and insert it into the tags. */ \ |
| 333 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid), kNoPP); \ | 333 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid), kNoPP); \ |
| 334 __ orr(R2, R2, Operand(TMP)); \ | 334 __ orr(R2, R2, Operand(TMP)); \ |
| 335 __ str(R2, FieldAddress(R0, type_name::tags_offset())); /* Tags. */ \ | 335 __ str(R2, FieldAddress(R0, type_name::tags_offset())); /* Tags. */ \ |
| 336 } \ | 336 } \ |
| 337 /* Set the length field. */ \ | 337 /* Set the length field. */ \ |
| 338 /* R0: new object start as a tagged pointer. */ \ | 338 /* R0: new object start as a tagged pointer. */ \ |
| 339 /* R1: new object end address. */ \ | 339 /* R1: new object end address. */ \ |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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); |
| 524 __ b(&neg_remainder, LT); | 524 __ b(&neg_remainder, LT); |
| 525 __ Lsl(R0, R1, 1); // Tag and move result to R0. | 525 __ LslImmediate(R0, R1, 1); // Tag and move result to R0. |
| 526 __ ret(); | 526 __ ret(); |
| 527 | 527 |
| 528 __ Bind(&neg_remainder); | 528 __ Bind(&neg_remainder); |
| 529 // Result is negative, adjust it. | 529 // Result is negative, adjust it. |
| 530 __ CompareRegisters(R0, ZR); | 530 __ CompareRegisters(R0, ZR); |
| 531 __ sub(TMP, R1, Operand(R0)); | 531 __ sub(TMP, R1, Operand(R0)); |
| 532 __ add(TMP2, R1, Operand(R0)); | 532 __ add(TMP2, R1, Operand(R0)); |
| 533 __ csel(R0, TMP2, TMP, GE); | 533 __ csel(R0, TMP2, TMP, GE); |
| 534 __ SmiTag(R0); | 534 __ SmiTag(R0); |
| 535 __ ret(); | 535 __ ret(); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 const Register result = R0; | 625 const Register result = R0; |
| 626 Label fall_through; | 626 Label fall_through; |
| 627 | 627 |
| 628 TestBothArgumentsSmis(assembler, &fall_through); | 628 TestBothArgumentsSmis(assembler, &fall_through); |
| 629 __ CompareImmediate( | 629 __ CompareImmediate( |
| 630 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)), PP); | 630 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)), PP); |
| 631 __ b(&fall_through, CS); | 631 __ b(&fall_through, CS); |
| 632 | 632 |
| 633 // Left is not a constant. | 633 // Left is not a constant. |
| 634 // Check if count too large for handling it inlined. | 634 // Check if count too large for handling it inlined. |
| 635 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 635 __ SmiUntag(TMP, right); // SmiUntag right into TMP. |
| 636 // Overflow test (preserve left, right, and TMP); | 636 // Overflow test (preserve left, right, and TMP); |
| 637 __ lslv(temp, left, TMP); | 637 __ lslv(temp, left, TMP); |
| 638 __ asrv(TMP2, temp, TMP); | 638 __ asrv(TMP2, temp, TMP); |
| 639 __ CompareRegisters(left, TMP2); | 639 __ CompareRegisters(left, TMP2); |
| 640 __ b(&fall_through, NE); // Overflow. | 640 __ b(&fall_through, NE); // Overflow. |
| 641 // Shift for result now we know there is no overflow. | 641 // Shift for result now we know there is no overflow. |
| 642 __ lslv(result, left, TMP); | 642 __ lslv(result, left, TMP); |
| 643 __ ret(); | 643 __ ret(); |
| 644 __ Bind(&fall_through); | 644 __ Bind(&fall_through); |
| 645 } | 645 } |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 | 988 |
| 989 __ Bind(&is_true); | 989 __ Bind(&is_true); |
| 990 __ mov(R0, true_reg); | 990 __ mov(R0, true_reg); |
| 991 | 991 |
| 992 __ Bind(&is_false); | 992 __ Bind(&is_false); |
| 993 __ ret(); | 993 __ ret(); |
| 994 | 994 |
| 995 __ Bind(&is_zero); | 995 __ Bind(&is_zero); |
| 996 // Check for negative zero by looking at the sign bit. | 996 // Check for negative zero by looking at the sign bit. |
| 997 __ fmovrd(R1, V0); | 997 __ fmovrd(R1, V0); |
| 998 __ Lsr(R1, R1, 63); | 998 __ LsrImmediate(R1, R1, 63); |
| 999 __ tsti(R1, 1); | 999 __ tsti(R1, 1); |
| 1000 __ csel(R0, true_reg, false_reg, NE); // Sign bit set. | 1000 __ csel(R0, true_reg, false_reg, NE); // Sign bit set. |
| 1001 __ ret(); | 1001 __ ret(); |
| 1002 } | 1002 } |
| 1003 | 1003 |
| 1004 | 1004 |
| 1005 void Intrinsifier::DoubleToInteger(Assembler* assembler) { | 1005 void Intrinsifier::DoubleToInteger(Assembler* assembler) { |
| 1006 Label fall_through; | 1006 Label fall_through; |
| 1007 | 1007 |
| 1008 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1008 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1065 | 1065 |
| 1066 __ ldr(R0, Address(SP, 0 * kWordSize)); // Receiver. | 1066 __ ldr(R0, Address(SP, 0 * kWordSize)); // Receiver. |
| 1067 __ ldr(R1, FieldAddress(R0, state_field.Offset())); // Field '_state'. | 1067 __ ldr(R1, FieldAddress(R0, state_field.Offset())); // Field '_state'. |
| 1068 | 1068 |
| 1069 // Addresses of _state[0]. | 1069 // Addresses of _state[0]. |
| 1070 const int64_t disp = | 1070 const int64_t disp = |
| 1071 Instance::DataOffsetFor(kTypedDataUint32ArrayCid) - kHeapObjectTag; | 1071 Instance::DataOffsetFor(kTypedDataUint32ArrayCid) - kHeapObjectTag; |
| 1072 | 1072 |
| 1073 __ LoadImmediate(R0, a_int_value, kNoPP); | 1073 __ LoadImmediate(R0, a_int_value, kNoPP); |
| 1074 __ LoadFromOffset(R2, R1, disp, kNoPP); | 1074 __ LoadFromOffset(R2, R1, disp, kNoPP); |
| 1075 __ Lsr(R3, R2, 32); | 1075 __ LsrImmediate(R3, R2, 32); |
| 1076 __ andi(R2, R2, 0xffffffff); | 1076 __ andi(R2, R2, 0xffffffff); |
| 1077 __ mul(R2, R0, R2); | 1077 __ mul(R2, R0, R2); |
| 1078 __ add(R2, R2, Operand(R3)); | 1078 __ add(R2, R2, Operand(R3)); |
| 1079 __ StoreToOffset(R2, R1, disp, kNoPP); | 1079 __ StoreToOffset(R2, R1, disp, kNoPP); |
| 1080 __ ret(); | 1080 __ ret(); |
| 1081 } | 1081 } |
| 1082 | 1082 |
| 1083 | 1083 |
| 1084 void Intrinsifier::ObjectEquals(Assembler* assembler) { | 1084 void Intrinsifier::ObjectEquals(Assembler* assembler) { |
| 1085 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1085 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 // Initialize the tags. | 1298 // Initialize the tags. |
| 1299 // R0: new object start as a tagged pointer. | 1299 // R0: new object start as a tagged pointer. |
| 1300 // R1: new object end address. | 1300 // R1: new object end address. |
| 1301 // R2: allocation size. | 1301 // R2: allocation size. |
| 1302 { | 1302 { |
| 1303 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 1303 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 1304 const Class& cls = | 1304 const Class& cls = |
| 1305 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1305 Class::Handle(isolate->object_store()->one_byte_string_class()); |
| 1306 | 1306 |
| 1307 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP); | 1307 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP); |
| 1308 __ Lsl(R2, R2, shift); | 1308 __ LslImmediate(R2, R2, shift); |
| 1309 __ csel(R2, R2, ZR, LS); | 1309 __ csel(R2, R2, ZR, LS); |
| 1310 | 1310 |
| 1311 // Get the class index and insert it into the tags. | 1311 // Get the class index and insert it into the tags. |
| 1312 // R2: size and bit tags. | 1312 // R2: size and bit tags. |
| 1313 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id()), kNoPP); | 1313 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id()), kNoPP); |
| 1314 __ orr(R2, R2, Operand(TMP)); | 1314 __ orr(R2, R2, Operand(TMP)); |
| 1315 __ str(R2, FieldAddress(R0, String::tags_offset())); // Store tags. | 1315 __ str(R2, FieldAddress(R0, String::tags_offset())); // Store tags. |
| 1316 } | 1316 } |
| 1317 | 1317 |
| 1318 // Set the length field using the saved length (R6). | 1318 // Set the length field using the saved length (R6). |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 Isolate* isolate = Isolate::Current(); | 1523 Isolate* isolate = Isolate::Current(); |
| 1524 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP); | 1524 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP); |
| 1525 // Set return value to Isolate::current_tag_. | 1525 // Set return value to Isolate::current_tag_. |
| 1526 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); | 1526 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); |
| 1527 __ ret(); | 1527 __ ret(); |
| 1528 } | 1528 } |
| 1529 | 1529 |
| 1530 } // namespace dart | 1530 } // namespace dart |
| 1531 | 1531 |
| 1532 #endif // defined TARGET_ARCH_ARM64 | 1532 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |