| 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 imm_s_fixed >>= 1; | 250 imm_s_fixed >>= 1; |
| 251 continue; | 251 continue; |
| 252 } | 252 } |
| 253 | 253 |
| 254 // 6. Otherwise, the value can't be encoded. | 254 // 6. Otherwise, the value can't be encoded. |
| 255 return false; | 255 return false; |
| 256 } | 256 } |
| 257 } | 257 } |
| 258 | 258 |
| 259 | 259 |
| 260 void Assembler::LoadPoolPointer(Register pp) { |
| 261 const intptr_t object_pool_pc_dist = |
| 262 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 263 CodeSize(); |
| 264 // PP <- Read(PC - object_pool_pc_dist). |
| 265 ldr(pp, Address::PC(-object_pool_pc_dist)); |
| 266 |
| 267 // When in the PP register, the pool pointer is untagged. When we |
| 268 // push it on the stack with PushPP it is tagged again. PopPP then untags |
| 269 // when restoring from the stack. This will make loading from the object |
| 270 // pool only one instruction for the first 4096 entries. Otherwise, because |
| 271 // the offset wouldn't be aligned, it would always be at least two |
| 272 // instructions. |
| 273 sub(pp, pp, Operand(kHeapObjectTag)); |
| 274 } |
| 275 |
| 260 void Assembler::LoadWordFromPoolOffset(Register dst, Register pp, | 276 void Assembler::LoadWordFromPoolOffset(Register dst, Register pp, |
| 261 uint32_t offset) { | 277 uint32_t offset) { |
| 262 ASSERT(dst != pp); | 278 ASSERT(dst != pp); |
| 263 if (Address::CanHoldOffset(offset)) { | 279 if (Address::CanHoldOffset(offset)) { |
| 264 ldr(dst, Address(pp, offset)); | 280 ldr(dst, Address(pp, offset)); |
| 265 } else { | 281 } else { |
| 266 const uint16_t offset_low = Utils::Low16Bits(offset); | 282 const uint16_t offset_low = Utils::Low16Bits(offset); |
| 267 const uint16_t offset_high = Utils::High16Bits(offset); | 283 const uint16_t offset_high = Utils::High16Bits(offset); |
| 268 movz(dst, offset_low, 0); | 284 movz(dst, offset_low, 0); |
| 269 if (offset_high != 0) { | 285 if (offset_high != 0) { |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 if (h3 != 0) { | 516 if (h3 != 0) { |
| 501 if (initialized) { | 517 if (initialized) { |
| 502 movk(reg, h3, 3); | 518 movk(reg, h3, 3); |
| 503 } else { | 519 } else { |
| 504 movz(reg, h3, 3); | 520 movz(reg, h3, 3); |
| 505 } | 521 } |
| 506 } | 522 } |
| 507 } | 523 } |
| 508 } | 524 } |
| 509 | 525 |
| 526 |
| 527 void Assembler::AddImmediate( |
| 528 Register dest, Register rn, int64_t imm, Register pp) { |
| 529 ASSERT(rn != TMP2); |
| 530 Operand op; |
| 531 if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) { |
| 532 add(dest, rn, op); |
| 533 } else if (Operand::CanHold(-imm, kXRegSizeInBits, &op) == |
| 534 Operand::Immediate) { |
| 535 sub(dest, rn, op); |
| 536 } else { |
| 537 LoadImmediate(TMP2, imm, pp); |
| 538 add(dest, rn, Operand(TMP2)); |
| 539 } |
| 540 } |
| 541 |
| 542 |
| 543 void Assembler::CompareImmediate(Register rn, int64_t imm, Register pp) { |
| 544 ASSERT(rn != TMP2); |
| 545 Operand op; |
| 546 if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) { |
| 547 cmp(rn, op); |
| 548 } else if (Operand::CanHold(-imm, kXRegSizeInBits, &op) == |
| 549 Operand::Immediate) { |
| 550 cmn(rn, op); |
| 551 } else { |
| 552 LoadImmediate(TMP2, imm, pp); |
| 553 cmp(rn, Operand(TMP2)); |
| 554 } |
| 555 } |
| 556 |
| 557 |
| 558 void Assembler::LoadFromOffset(Register dest, Register base, int32_t offset) { |
| 559 ASSERT(base != TMP2); |
| 560 if (Address::CanHoldOffset(offset)) { |
| 561 ldr(dest, Address(base, offset)); |
| 562 } else if (Address::CanHoldOffset(offset, Address::PreIndex)) { |
| 563 mov(TMP2, base); |
| 564 ldr(dest, Address(TMP2, offset, Address::PreIndex)); |
| 565 } else { |
| 566 // Since offset is 32-bits, it won't be loaded from the pool. |
| 567 AddImmediate(TMP2, base, offset, kNoRegister); |
| 568 ldr(dest, Address(TMP2)); |
| 569 } |
| 570 } |
| 571 |
| 572 |
| 573 void Assembler::StoreToOffset(Register src, Register base, int32_t offset) { |
| 574 ASSERT(src != TMP2); |
| 575 ASSERT(base != TMP2); |
| 576 if (Address::CanHoldOffset(offset)) { |
| 577 str(src, Address(base, offset)); |
| 578 } else if (Address::CanHoldOffset(offset, Address::PreIndex)) { |
| 579 mov(TMP2, base); |
| 580 str(src, Address(TMP2, offset, Address::PreIndex)); |
| 581 } else { |
| 582 // Since offset is 32-bits, it won't be loaded from the pool. |
| 583 AddImmediate(TMP2, base, offset, kNoRegister); |
| 584 str(src, Address(TMP2)); |
| 585 } |
| 586 } |
| 587 |
| 588 |
| 589 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { |
| 590 // Reserve space for arguments and align frame before entering |
| 591 // the C++ world. |
| 592 AddImmediate(SP, SP, -frame_space, kNoRegister); |
| 593 if (OS::ActivationFrameAlignment() > 1) { |
| 594 mov(TMP, SP); // SP can't be register operand of andi. |
| 595 andi(SP, TMP, ~(OS::ActivationFrameAlignment() - 1)); |
| 596 } |
| 597 } |
| 598 |
| 599 |
| 600 void Assembler::EnterDartFrame(intptr_t frame_size) { |
| 601 adr(TMP, 0); // TMP gets PC of this instruction. |
| 602 Push(TMP); // Save PC Marker. |
| 603 Push(LR); // Save return address. |
| 604 Push(FP); // Save FP. |
| 605 PushPP(); // Save PP. |
| 606 |
| 607 // Set FP to saved previous FP. |
| 608 add(FP, SP, Operand(1 * kWordSize)); |
| 609 |
| 610 // Load the pool pointer. |
| 611 LoadPoolPointer(PP); |
| 612 |
| 613 // Reserve space. |
| 614 sub(SP, SP, Operand(frame_size)); |
| 615 } |
| 616 |
| 617 |
| 618 void Assembler::LeaveDartFrame() { |
| 619 sub(SP, FP, Operand(1 * kWordSize)); |
| 620 PopPP(); // Restore pool pointer. |
| 621 Pop(FP); // Restore frame pointer. |
| 622 Pop(LR); // Restore return address. |
| 623 Pop(TMP); // Pop PC marker, and restore SP. |
| 624 } |
| 625 |
| 626 |
| 627 void Assembler::CallRuntime(const RuntimeEntry& entry, |
| 628 intptr_t argument_count) { |
| 629 entry.Call(this, argument_count); |
| 630 } |
| 631 |
| 510 } // namespace dart | 632 } // namespace dart |
| 511 | 633 |
| 512 #endif // defined TARGET_ARCH_ARM64 | 634 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |