| OLD | NEW |
| 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 #ifndef VM_ASSEMBLER_ARM_H_ | 5 #ifndef VM_ASSEMBLER_ARM_H_ |
| 6 #define VM_ASSEMBLER_ARM_H_ | 6 #define VM_ASSEMBLER_ARM_H_ |
| 7 | 7 |
| 8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_arm.h directly; use assembler.h instead. | 9 #error Do not include assembler_arm.h directly; use assembler.h instead. |
| 10 #endif | 10 #endif |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 ASSERT(Utils::IsAbsoluteUint(12, offset)); | 224 ASSERT(Utils::IsAbsoluteUint(12, offset)); |
| 225 kind_ = Immediate; | 225 kind_ = Immediate; |
| 226 if (offset < 0) { | 226 if (offset < 0) { |
| 227 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign. | 227 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign. |
| 228 } else { | 228 } else { |
| 229 encoding_ = am | offset; | 229 encoding_ = am | offset; |
| 230 } | 230 } |
| 231 encoding_ |= static_cast<uint32_t>(rn) << kRnShift; | 231 encoding_ |= static_cast<uint32_t>(rn) << kRnShift; |
| 232 } | 232 } |
| 233 | 233 |
| 234 // There is no register offset mode unless Mode is Offset, in which case the |
| 235 // shifted register case below should be used. |
| 236 Address(Register rn, Register r, Mode am) { |
| 237 UNREACHABLE(); |
| 238 } |
| 239 |
| 234 Address(Register rn, Register rm, | 240 Address(Register rn, Register rm, |
| 235 Shift shift = LSL, uint32_t shift_imm = 0, Mode am = Offset) { | 241 Shift shift = LSL, uint32_t shift_imm = 0, Mode am = Offset) { |
| 236 Operand o(rm, shift, shift_imm); | 242 Operand o(rm, shift, shift_imm); |
| 237 | 243 |
| 238 if ((shift == LSL) && (shift_imm == 0)) { | 244 if ((shift == LSL) && (shift_imm == 0)) { |
| 239 kind_ = IndexRegister; | 245 kind_ = IndexRegister; |
| 240 } else { | 246 } else { |
| 241 kind_ = ScaledIndexRegister; | 247 kind_ = ScaledIndexRegister; |
| 242 } | 248 } |
| 243 encoding_ = o.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift); | 249 encoding_ = o.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift); |
| 244 } | 250 } |
| 245 | 251 |
| 252 // There is no shifted register mode with a register shift. |
| 253 Address(Register rn, Register rm, Shift shift, Register r, Mode am = Offset) { |
| 254 UNREACHABLE(); |
| 255 } |
| 256 |
| 246 static OperandSize OperandSizeFor(intptr_t cid); | 257 static OperandSize OperandSizeFor(intptr_t cid); |
| 247 | 258 |
| 248 static bool CanHoldLoadOffset(OperandSize size, | 259 static bool CanHoldLoadOffset(OperandSize size, |
| 249 int32_t offset, | 260 int32_t offset, |
| 250 int32_t* offset_mask); | 261 int32_t* offset_mask); |
| 251 static bool CanHoldStoreOffset(OperandSize size, | 262 static bool CanHoldStoreOffset(OperandSize size, |
| 252 int32_t offset, | 263 int32_t offset, |
| 253 int32_t* offset_mask); | 264 int32_t* offset_mask); |
| 254 static bool CanHoldImmediateOffset(bool is_load, | 265 static bool CanHoldImmediateOffset(bool is_load, |
| 255 intptr_t cid, | 266 intptr_t cid, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 272 | 283 |
| 273 friend class Assembler; | 284 friend class Assembler; |
| 274 }; | 285 }; |
| 275 | 286 |
| 276 | 287 |
| 277 class FieldAddress : public Address { | 288 class FieldAddress : public Address { |
| 278 public: | 289 public: |
| 279 FieldAddress(Register base, int32_t disp) | 290 FieldAddress(Register base, int32_t disp) |
| 280 : Address(base, disp - kHeapObjectTag) { } | 291 : Address(base, disp - kHeapObjectTag) { } |
| 281 | 292 |
| 293 FieldAddress(Register base, Register r) : Address(base) { |
| 294 UNREACHABLE(); |
| 295 } |
| 296 |
| 282 FieldAddress(const FieldAddress& other) : Address(other) { } | 297 FieldAddress(const FieldAddress& other) : Address(other) { } |
| 283 | 298 |
| 284 FieldAddress& operator=(const FieldAddress& other) { | 299 FieldAddress& operator=(const FieldAddress& other) { |
| 285 Address::operator=(other); | 300 Address::operator=(other); |
| 286 return *this; | 301 return *this; |
| 287 } | 302 } |
| 288 }; | 303 }; |
| 289 | 304 |
| 290 | 305 |
| 291 class Assembler : public ValueObject { | 306 class Assembler : public ValueObject { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 void movs(Register rd, Operand o, Condition cond = AL); | 404 void movs(Register rd, Operand o, Condition cond = AL); |
| 390 | 405 |
| 391 void bic(Register rd, Register rn, Operand o, Condition cond = AL); | 406 void bic(Register rd, Register rn, Operand o, Condition cond = AL); |
| 392 void bics(Register rd, Register rn, Operand o, Condition cond = AL); | 407 void bics(Register rd, Register rn, Operand o, Condition cond = AL); |
| 393 | 408 |
| 394 void mvn(Register rd, Operand o, Condition cond = AL); | 409 void mvn(Register rd, Operand o, Condition cond = AL); |
| 395 void mvns(Register rd, Operand o, Condition cond = AL); | 410 void mvns(Register rd, Operand o, Condition cond = AL); |
| 396 | 411 |
| 397 // Miscellaneous data-processing instructions. | 412 // Miscellaneous data-processing instructions. |
| 398 void clz(Register rd, Register rm, Condition cond = AL); | 413 void clz(Register rd, Register rm, Condition cond = AL); |
| 399 void movw(Register rd, uint16_t imm16, Condition cond = AL); | |
| 400 void movt(Register rd, uint16_t imm16, Condition cond = AL); | |
| 401 | 414 |
| 402 // Multiply instructions. | 415 // Multiply instructions. |
| 403 void mul(Register rd, Register rn, Register rm, Condition cond = AL); | 416 void mul(Register rd, Register rn, Register rm, Condition cond = AL); |
| 404 void muls(Register rd, Register rn, Register rm, Condition cond = AL); | 417 void muls(Register rd, Register rn, Register rm, Condition cond = AL); |
| 405 void mla(Register rd, Register rn, Register rm, Register ra, | 418 void mla(Register rd, Register rn, Register rm, Register ra, |
| 406 Condition cond = AL); | 419 Condition cond = AL); |
| 407 void mls(Register rd, Register rn, Register rm, Register ra, | 420 void mls(Register rd, Register rn, Register rm, Register ra, |
| 408 Condition cond = AL); | 421 Condition cond = AL); |
| 409 void smull(Register rd_lo, Register rd_hi, Register rn, Register rm, | 422 void smull(Register rd_lo, Register rd_hi, Register rn, Register rm, |
| 410 Condition cond = AL); | 423 Condition cond = AL); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 void BranchPatchable(const ExternalLabel* label); | 588 void BranchPatchable(const ExternalLabel* label); |
| 576 | 589 |
| 577 // Branch and link to an entry address. Call sequence is never patched. | 590 // Branch and link to an entry address. Call sequence is never patched. |
| 578 void BranchLink(const ExternalLabel* label); | 591 void BranchLink(const ExternalLabel* label); |
| 579 | 592 |
| 580 // Branch and link to an entry address. Call sequence can be patched. | 593 // Branch and link to an entry address. Call sequence can be patched. |
| 581 void BranchLinkPatchable(const ExternalLabel* label); | 594 void BranchLinkPatchable(const ExternalLabel* label); |
| 582 | 595 |
| 583 // Branch and link to [base + offset]. Call sequence is never patched. | 596 // Branch and link to [base + offset]. Call sequence is never patched. |
| 584 void BranchLinkOffset(Register base, int32_t offset); | 597 void BranchLinkOffset(Register base, int32_t offset); |
| 598 void BranchLinkOffset(Register base, Register r) { |
| 599 UNREACHABLE(); |
| 600 } |
| 585 | 601 |
| 586 // Add signed immediate value to rd. May clobber IP. | 602 // Add signed immediate value to rd. May clobber IP. |
| 587 void AddImmediate(Register rd, int32_t value, Condition cond = AL); | 603 void AddImmediate(Register rd, int32_t value, Condition cond = AL); |
| 588 void AddImmediate(Register rd, Register rn, int32_t value, | 604 void AddImmediate(Register rd, Register rn, int32_t value, |
| 589 Condition cond = AL); | 605 Condition cond = AL); |
| 590 void AddImmediateSetFlags(Register rd, Register rn, int32_t value, | 606 void AddImmediateSetFlags(Register rd, Register rn, int32_t value, |
| 591 Condition cond = AL); | 607 Condition cond = AL); |
| 592 void SubImmediateSetFlags(Register rd, Register rn, int32_t value, | 608 void SubImmediateSetFlags(Register rd, Register rn, int32_t value, |
| 593 Condition cond = AL); | 609 Condition cond = AL); |
| 594 void AndImmediate(Register rd, Register rs, int32_t imm, Condition cond = AL); | 610 void AndImmediate(Register rd, Register rs, int32_t imm, Condition cond = AL); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 void Push(Register rd, Condition cond = AL); | 723 void Push(Register rd, Condition cond = AL); |
| 708 void Pop(Register rd, Condition cond = AL); | 724 void Pop(Register rd, Condition cond = AL); |
| 709 | 725 |
| 710 void PushList(RegList regs, Condition cond = AL); | 726 void PushList(RegList regs, Condition cond = AL); |
| 711 void PopList(RegList regs, Condition cond = AL); | 727 void PopList(RegList regs, Condition cond = AL); |
| 712 | 728 |
| 713 void MoveRegister(Register rd, Register rm, Condition cond = AL); | 729 void MoveRegister(Register rd, Register rm, Condition cond = AL); |
| 714 | 730 |
| 715 // Convenience shift instructions. Use mov instruction with shifter operand | 731 // Convenience shift instructions. Use mov instruction with shifter operand |
| 716 // for variants setting the status flags. | 732 // for variants setting the status flags. |
| 717 void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); | 733 void Lsl(Register rd, Register rm, const Operand& shift_imm, |
| 734 Condition cond = AL); |
| 718 void Lsl(Register rd, Register rm, Register rs, Condition cond = AL); | 735 void Lsl(Register rd, Register rm, Register rs, Condition cond = AL); |
| 719 void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); | 736 void Lsr(Register rd, Register rm, const Operand& shift_imm, |
| 737 Condition cond = AL); |
| 720 void Lsr(Register rd, Register rm, Register rs, Condition cond = AL); | 738 void Lsr(Register rd, Register rm, Register rs, Condition cond = AL); |
| 721 void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); | 739 void Asr(Register rd, Register rm, const Operand& shift_imm, |
| 740 Condition cond = AL); |
| 722 void Asr(Register rd, Register rm, Register rs, Condition cond = AL); | 741 void Asr(Register rd, Register rm, Register rs, Condition cond = AL); |
| 723 void Asrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); | 742 void Asrs(Register rd, Register rm, const Operand& shift_imm, |
| 724 void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); | 743 Condition cond = AL); |
| 744 void Ror(Register rd, Register rm, const Operand& shift_imm, |
| 745 Condition cond = AL); |
| 725 void Ror(Register rd, Register rm, Register rs, Condition cond = AL); | 746 void Ror(Register rd, Register rm, Register rs, Condition cond = AL); |
| 726 void Rrx(Register rd, Register rm, Condition cond = AL); | 747 void Rrx(Register rd, Register rm, Condition cond = AL); |
| 727 | 748 |
| 728 // Fill rd with the sign of rm. | 749 // Fill rd with the sign of rm. |
| 729 void SignFill(Register rd, Register rm, Condition cond = AL); | 750 void SignFill(Register rd, Register rm, Condition cond = AL); |
| 730 | 751 |
| 731 void Vreciprocalqs(QRegister qd, QRegister qm); | 752 void Vreciprocalqs(QRegister qd, QRegister qm); |
| 732 void VreciprocalSqrtqs(QRegister qd, QRegister qm); | 753 void VreciprocalSqrtqs(QRegister qd, QRegister qm); |
| 733 // If qm must be preserved, then provide a (non-QTMP) temporary. | 754 // If qm must be preserved, then provide a (non-QTMP) temporary. |
| 734 void Vsqrtqs(QRegister qd, QRegister qm, QRegister temp); | 755 void Vsqrtqs(QRegister qd, QRegister qm, QRegister temp); |
| 735 void Vdivqs(QRegister qd, QRegister qn, QRegister qm); | 756 void Vdivqs(QRegister qd, QRegister qn, QRegister qm); |
| 736 | 757 |
| 737 void SmiTag(Register reg, Condition cond = AL) { | 758 void SmiTag(Register reg, Condition cond = AL) { |
| 738 Lsl(reg, reg, kSmiTagSize, cond); | 759 Lsl(reg, reg, Operand(kSmiTagSize), cond); |
| 739 } | 760 } |
| 740 | 761 |
| 741 void SmiTag(Register dst, Register src, Condition cond = AL) { | 762 void SmiTag(Register dst, Register src, Condition cond = AL) { |
| 742 Lsl(dst, src, kSmiTagSize, cond); | 763 Lsl(dst, src, Operand(kSmiTagSize), cond); |
| 743 } | 764 } |
| 744 | 765 |
| 745 void SmiUntag(Register reg, Condition cond = AL) { | 766 void SmiUntag(Register reg, Condition cond = AL) { |
| 746 Asr(reg, reg, kSmiTagSize, cond); | 767 Asr(reg, reg, Operand(kSmiTagSize), cond); |
| 747 } | 768 } |
| 748 | 769 |
| 749 void SmiUntag(Register dst, Register src, Condition cond = AL) { | 770 void SmiUntag(Register dst, Register src, Condition cond = AL) { |
| 750 Asr(dst, src, kSmiTagSize, cond); | 771 Asr(dst, src, Operand(kSmiTagSize), cond); |
| 751 } | 772 } |
| 752 | 773 |
| 753 // Untag the value in the register assuming it is a smi. | 774 // Untag the value in the register assuming it is a smi. |
| 754 // Untagging shifts tag bit into the carry flag - if carry is clear | 775 // Untagging shifts tag bit into the carry flag - if carry is clear |
| 755 // assumption was correct. In this case jump to the is_smi label. | 776 // assumption was correct. In this case jump to the is_smi label. |
| 756 // Otherwise fall-through. | 777 // Otherwise fall-through. |
| 757 void SmiUntag(Register dst, Register src, Label* is_smi) { | 778 void SmiUntag(Register dst, Register src, Label* is_smi) { |
| 758 ASSERT(kSmiTagSize == 1); | 779 ASSERT(kSmiTagSize == 1); |
| 759 Asrs(dst, src, kSmiTagSize); | 780 Asrs(dst, src, Operand(kSmiTagSize)); |
| 760 b(is_smi, CC); | 781 b(is_smi, CC); |
| 761 } | 782 } |
| 762 | 783 |
| 763 // Function frame setup and tear down. | 784 // Function frame setup and tear down. |
| 764 void EnterFrame(RegList regs, intptr_t frame_space); | 785 void EnterFrame(RegList regs, intptr_t frame_space); |
| 765 void LeaveFrame(RegList regs); | 786 void LeaveFrame(RegList regs); |
| 766 void Ret(); | 787 void Ret(); |
| 767 void ReserveAlignedFrameSpace(intptr_t frame_space); | 788 void ReserveAlignedFrameSpace(intptr_t frame_space); |
| 768 | 789 |
| 769 // Create a frame for calling into runtime that preserves all volatile | 790 // Create a frame for calling into runtime that preserves all volatile |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 853 allow_constant_pool_ = b; | 874 allow_constant_pool_ = b; |
| 854 } | 875 } |
| 855 | 876 |
| 856 private: | 877 private: |
| 857 AssemblerBuffer buffer_; // Contains position independent code. | 878 AssemblerBuffer buffer_; // Contains position independent code. |
| 858 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. | 879 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. |
| 859 int32_t prologue_offset_; | 880 int32_t prologue_offset_; |
| 860 | 881 |
| 861 bool use_far_branches_; | 882 bool use_far_branches_; |
| 862 | 883 |
| 884 // If you are thinking of using one or both of these instructions directly, |
| 885 // instead LoadImmediate should probably be used. |
| 886 void movw(Register rd, uint16_t imm16, Condition cond = AL); |
| 887 void movt(Register rd, uint16_t imm16, Condition cond = AL); |
| 888 |
| 863 int32_t AddObject(const Object& obj); | 889 int32_t AddObject(const Object& obj); |
| 864 int32_t AddExternalLabel(const ExternalLabel* label); | 890 int32_t AddExternalLabel(const ExternalLabel* label); |
| 865 | 891 |
| 866 void BindARMv6(Label* label); | 892 void BindARMv6(Label* label); |
| 867 void BindARMv7(Label* label); | 893 void BindARMv7(Label* label); |
| 868 | 894 |
| 869 class CodeComment : public ZoneAllocated { | 895 class CodeComment : public ZoneAllocated { |
| 870 public: | 896 public: |
| 871 CodeComment(intptr_t pc_offset, const String& comment) | 897 CodeComment(intptr_t pc_offset, const String& comment) |
| 872 : pc_offset_(pc_offset), comment_(comment) { } | 898 : pc_offset_(pc_offset), comment_(comment) { } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 Register value, | 1019 Register value, |
| 994 Label* no_update); | 1020 Label* no_update); |
| 995 | 1021 |
| 996 DISALLOW_ALLOCATION(); | 1022 DISALLOW_ALLOCATION(); |
| 997 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1023 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 998 }; | 1024 }; |
| 999 | 1025 |
| 1000 } // namespace dart | 1026 } // namespace dart |
| 1001 | 1027 |
| 1002 #endif // VM_ASSEMBLER_ARM_H_ | 1028 #endif // VM_ASSEMBLER_ARM_H_ |
| OLD | NEW |