OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_ARM64_MACRO_ASSEMBLER_ARM64_H_ | 5 #ifndef V8_ARM64_MACRO_ASSEMBLER_ARM64_H_ |
6 #define V8_ARM64_MACRO_ASSEMBLER_ARM64_H_ | 6 #define V8_ARM64_MACRO_ASSEMBLER_ARM64_H_ |
7 | 7 |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "src/globals.h" | 10 #include "src/globals.h" |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 inline void Fmov(FPRegister fd, Register rn); | 359 inline void Fmov(FPRegister fd, Register rn); |
360 // Provide explicit double and float interfaces for FP immediate moves, rather | 360 // Provide explicit double and float interfaces for FP immediate moves, rather |
361 // than relying on implicit C++ casts. This allows signalling NaNs to be | 361 // than relying on implicit C++ casts. This allows signalling NaNs to be |
362 // preserved when the immediate matches the format of fd. Most systems convert | 362 // preserved when the immediate matches the format of fd. Most systems convert |
363 // signalling NaNs to quiet NaNs when converting between float and double. | 363 // signalling NaNs to quiet NaNs when converting between float and double. |
364 inline void Fmov(FPRegister fd, double imm); | 364 inline void Fmov(FPRegister fd, double imm); |
365 inline void Fmov(FPRegister fd, float imm); | 365 inline void Fmov(FPRegister fd, float imm); |
366 // Provide a template to allow other types to be converted automatically. | 366 // Provide a template to allow other types to be converted automatically. |
367 template<typename T> | 367 template<typename T> |
368 void Fmov(FPRegister fd, T imm) { | 368 void Fmov(FPRegister fd, T imm) { |
369 ASSERT(allow_macro_instructions_); | 369 DCHECK(allow_macro_instructions_); |
370 Fmov(fd, static_cast<double>(imm)); | 370 Fmov(fd, static_cast<double>(imm)); |
371 } | 371 } |
372 inline void Fmov(Register rd, FPRegister fn); | 372 inline void Fmov(Register rd, FPRegister fn); |
373 inline void Fmsub(const FPRegister& fd, | 373 inline void Fmsub(const FPRegister& fd, |
374 const FPRegister& fn, | 374 const FPRegister& fn, |
375 const FPRegister& fm, | 375 const FPRegister& fm, |
376 const FPRegister& fa); | 376 const FPRegister& fa); |
377 inline void Fmul(const FPRegister& fd, | 377 inline void Fmul(const FPRegister& fd, |
378 const FPRegister& fn, | 378 const FPRegister& fn, |
379 const FPRegister& fm); | 379 const FPRegister& fm); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 // allows push requests to be queued up, then flushed at once. The | 612 // allows push requests to be queued up, then flushed at once. The |
613 // MacroAssembler will try to generate the most efficient sequence required. | 613 // MacroAssembler will try to generate the most efficient sequence required. |
614 // | 614 // |
615 // Unlike the other Push and Pop macros, PushPopQueue can handle mixed sets of | 615 // Unlike the other Push and Pop macros, PushPopQueue can handle mixed sets of |
616 // register sizes and types. | 616 // register sizes and types. |
617 class PushPopQueue { | 617 class PushPopQueue { |
618 public: | 618 public: |
619 explicit PushPopQueue(MacroAssembler* masm) : masm_(masm), size_(0) { } | 619 explicit PushPopQueue(MacroAssembler* masm) : masm_(masm), size_(0) { } |
620 | 620 |
621 ~PushPopQueue() { | 621 ~PushPopQueue() { |
622 ASSERT(queued_.empty()); | 622 DCHECK(queued_.empty()); |
623 } | 623 } |
624 | 624 |
625 void Queue(const CPURegister& rt) { | 625 void Queue(const CPURegister& rt) { |
626 size_ += rt.SizeInBytes(); | 626 size_ += rt.SizeInBytes(); |
627 queued_.push_back(rt); | 627 queued_.push_back(rt); |
628 } | 628 } |
629 | 629 |
630 enum PreambleDirective { | 630 enum PreambleDirective { |
631 WITH_PREAMBLE, | 631 WITH_PREAMBLE, |
632 SKIP_PREAMBLE | 632 SKIP_PREAMBLE |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
764 // Floating-point registers are popped after general-purpose registers, and | 764 // Floating-point registers are popped after general-purpose registers, and |
765 // thus come from higher addresses. | 765 // thus come from higher addresses. |
766 // | 766 // |
767 // This method must not be called unless the current stack pointer (as set by | 767 // This method must not be called unless the current stack pointer (as set by |
768 // SetStackPointer) is the system stack pointer (csp), and is aligned to | 768 // SetStackPointer) is the system stack pointer (csp), and is aligned to |
769 // ActivationFrameAlignment(). | 769 // ActivationFrameAlignment(). |
770 void PopCalleeSavedRegisters(); | 770 void PopCalleeSavedRegisters(); |
771 | 771 |
772 // Set the current stack pointer, but don't generate any code. | 772 // Set the current stack pointer, but don't generate any code. |
773 inline void SetStackPointer(const Register& stack_pointer) { | 773 inline void SetStackPointer(const Register& stack_pointer) { |
774 ASSERT(!TmpList()->IncludesAliasOf(stack_pointer)); | 774 DCHECK(!TmpList()->IncludesAliasOf(stack_pointer)); |
775 sp_ = stack_pointer; | 775 sp_ = stack_pointer; |
776 } | 776 } |
777 | 777 |
778 // Return the current stack pointer, as set by SetStackPointer. | 778 // Return the current stack pointer, as set by SetStackPointer. |
779 inline const Register& StackPointer() const { | 779 inline const Register& StackPointer() const { |
780 return sp_; | 780 return sp_; |
781 } | 781 } |
782 | 782 |
783 // Align csp for a frame, as per ActivationFrameAlignment, and make it the | 783 // Align csp for a frame, as per ActivationFrameAlignment, and make it the |
784 // current stack pointer. | 784 // current stack pointer. |
785 inline void AlignAndSetCSPForFrame() { | 785 inline void AlignAndSetCSPForFrame() { |
786 int sp_alignment = ActivationFrameAlignment(); | 786 int sp_alignment = ActivationFrameAlignment(); |
787 // AAPCS64 mandates at least 16-byte alignment. | 787 // AAPCS64 mandates at least 16-byte alignment. |
788 ASSERT(sp_alignment >= 16); | 788 DCHECK(sp_alignment >= 16); |
789 ASSERT(IsPowerOf2(sp_alignment)); | 789 DCHECK(IsPowerOf2(sp_alignment)); |
790 Bic(csp, StackPointer(), sp_alignment - 1); | 790 Bic(csp, StackPointer(), sp_alignment - 1); |
791 SetStackPointer(csp); | 791 SetStackPointer(csp); |
792 } | 792 } |
793 | 793 |
794 // Push the system stack pointer (csp) down to allow the same to be done to | 794 // Push the system stack pointer (csp) down to allow the same to be done to |
795 // the current stack pointer (according to StackPointer()). This must be | 795 // the current stack pointer (according to StackPointer()). This must be |
796 // called _before_ accessing the memory. | 796 // called _before_ accessing the memory. |
797 // | 797 // |
798 // This is necessary when pushing or otherwise adding things to the stack, to | 798 // This is necessary when pushing or otherwise adding things to the stack, to |
799 // satisfy the AAPCS64 constraint that the memory below the system stack | 799 // satisfy the AAPCS64 constraint that the memory below the system stack |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 // Load both TrueValue and FalseValue roots. | 834 // Load both TrueValue and FalseValue roots. |
835 void LoadTrueFalseRoots(Register true_root, Register false_root); | 835 void LoadTrueFalseRoots(Register true_root, Register false_root); |
836 | 836 |
837 void LoadHeapObject(Register dst, Handle<HeapObject> object); | 837 void LoadHeapObject(Register dst, Handle<HeapObject> object); |
838 | 838 |
839 void LoadObject(Register result, Handle<Object> object) { | 839 void LoadObject(Register result, Handle<Object> object) { |
840 AllowDeferredHandleDereference heap_object_check; | 840 AllowDeferredHandleDereference heap_object_check; |
841 if (object->IsHeapObject()) { | 841 if (object->IsHeapObject()) { |
842 LoadHeapObject(result, Handle<HeapObject>::cast(object)); | 842 LoadHeapObject(result, Handle<HeapObject>::cast(object)); |
843 } else { | 843 } else { |
844 ASSERT(object->IsSmi()); | 844 DCHECK(object->IsSmi()); |
845 Mov(result, Operand(object)); | 845 Mov(result, Operand(object)); |
846 } | 846 } |
847 } | 847 } |
848 | 848 |
849 static int SafepointRegisterStackIndex(int reg_code); | 849 static int SafepointRegisterStackIndex(int reg_code); |
850 | 850 |
851 // This is required for compatibility with architecture independant code. | 851 // This is required for compatibility with architecture independant code. |
852 // Remove if not needed. | 852 // Remove if not needed. |
853 inline void Move(Register dst, Register src) { Mov(dst, src); } | 853 inline void Move(Register dst, Register src) { Mov(dst, src); } |
854 | 854 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
974 // Try to represent a double as a signed 32-bit int. | 974 // Try to represent a double as a signed 32-bit int. |
975 // This succeeds if the result compares equal to the input, so inputs of -0.0 | 975 // This succeeds if the result compares equal to the input, so inputs of -0.0 |
976 // are represented as 0 and handled as a success. | 976 // are represented as 0 and handled as a success. |
977 // | 977 // |
978 // On output the Z flag is set if the operation was successful. | 978 // On output the Z flag is set if the operation was successful. |
979 void TryRepresentDoubleAsInt32(Register as_int, | 979 void TryRepresentDoubleAsInt32(Register as_int, |
980 FPRegister value, | 980 FPRegister value, |
981 FPRegister scratch_d, | 981 FPRegister scratch_d, |
982 Label* on_successful_conversion = NULL, | 982 Label* on_successful_conversion = NULL, |
983 Label* on_failed_conversion = NULL) { | 983 Label* on_failed_conversion = NULL) { |
984 ASSERT(as_int.Is32Bits()); | 984 DCHECK(as_int.Is32Bits()); |
985 TryRepresentDoubleAsInt(as_int, value, scratch_d, on_successful_conversion, | 985 TryRepresentDoubleAsInt(as_int, value, scratch_d, on_successful_conversion, |
986 on_failed_conversion); | 986 on_failed_conversion); |
987 } | 987 } |
988 | 988 |
989 // Try to represent a double as a signed 64-bit int. | 989 // Try to represent a double as a signed 64-bit int. |
990 // This succeeds if the result compares equal to the input, so inputs of -0.0 | 990 // This succeeds if the result compares equal to the input, so inputs of -0.0 |
991 // are represented as 0 and handled as a success. | 991 // are represented as 0 and handled as a success. |
992 // | 992 // |
993 // On output the Z flag is set if the operation was successful. | 993 // On output the Z flag is set if the operation was successful. |
994 void TryRepresentDoubleAsInt64(Register as_int, | 994 void TryRepresentDoubleAsInt64(Register as_int, |
995 FPRegister value, | 995 FPRegister value, |
996 FPRegister scratch_d, | 996 FPRegister scratch_d, |
997 Label* on_successful_conversion = NULL, | 997 Label* on_successful_conversion = NULL, |
998 Label* on_failed_conversion = NULL) { | 998 Label* on_failed_conversion = NULL) { |
999 ASSERT(as_int.Is64Bits()); | 999 DCHECK(as_int.Is64Bits()); |
1000 TryRepresentDoubleAsInt(as_int, value, scratch_d, on_successful_conversion, | 1000 TryRepresentDoubleAsInt(as_int, value, scratch_d, on_successful_conversion, |
1001 on_failed_conversion); | 1001 on_failed_conversion); |
1002 } | 1002 } |
1003 | 1003 |
1004 // ---- Object Utilities ---- | 1004 // ---- Object Utilities ---- |
1005 | 1005 |
1006 // Copy fields from 'src' to 'dst', where both are tagged objects. | 1006 // Copy fields from 'src' to 'dst', where both are tagged objects. |
1007 // The 'temps' list is a list of X registers which can be used for scratch | 1007 // The 'temps' list is a list of X registers which can be used for scratch |
1008 // values. The temps list must include at least one register. | 1008 // values. The temps list must include at least one register. |
1009 // | 1009 // |
(...skipping 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2197 } | 2197 } |
2198 previous_allow_macro_instructions_ = masm_->allow_macro_instructions(); | 2198 previous_allow_macro_instructions_ = masm_->allow_macro_instructions(); |
2199 masm_->set_allow_macro_instructions(false); | 2199 masm_->set_allow_macro_instructions(false); |
2200 #endif | 2200 #endif |
2201 } | 2201 } |
2202 | 2202 |
2203 ~InstructionAccurateScope() { | 2203 ~InstructionAccurateScope() { |
2204 masm_->EndBlockPools(); | 2204 masm_->EndBlockPools(); |
2205 #ifdef DEBUG | 2205 #ifdef DEBUG |
2206 if (start_.is_bound()) { | 2206 if (start_.is_bound()) { |
2207 ASSERT(masm_->SizeOfCodeGeneratedSince(&start_) == size_); | 2207 DCHECK(masm_->SizeOfCodeGeneratedSince(&start_) == size_); |
2208 } | 2208 } |
2209 masm_->set_allow_macro_instructions(previous_allow_macro_instructions_); | 2209 masm_->set_allow_macro_instructions(previous_allow_macro_instructions_); |
2210 #endif | 2210 #endif |
2211 } | 2211 } |
2212 | 2212 |
2213 private: | 2213 private: |
2214 MacroAssembler* masm_; | 2214 MacroAssembler* masm_; |
2215 #ifdef DEBUG | 2215 #ifdef DEBUG |
2216 size_t size_; | 2216 size_t size_; |
2217 Label start_; | 2217 Label start_; |
2218 bool previous_allow_macro_instructions_; | 2218 bool previous_allow_macro_instructions_; |
2219 #endif | 2219 #endif |
2220 }; | 2220 }; |
2221 | 2221 |
2222 | 2222 |
2223 // This scope utility allows scratch registers to be managed safely. The | 2223 // This scope utility allows scratch registers to be managed safely. The |
2224 // MacroAssembler's TmpList() (and FPTmpList()) is used as a pool of scratch | 2224 // MacroAssembler's TmpList() (and FPTmpList()) is used as a pool of scratch |
2225 // registers. These registers can be allocated on demand, and will be returned | 2225 // registers. These registers can be allocated on demand, and will be returned |
2226 // at the end of the scope. | 2226 // at the end of the scope. |
2227 // | 2227 // |
2228 // When the scope ends, the MacroAssembler's lists will be restored to their | 2228 // When the scope ends, the MacroAssembler's lists will be restored to their |
2229 // original state, even if the lists were modified by some other means. | 2229 // original state, even if the lists were modified by some other means. |
2230 class UseScratchRegisterScope { | 2230 class UseScratchRegisterScope { |
2231 public: | 2231 public: |
2232 explicit UseScratchRegisterScope(MacroAssembler* masm) | 2232 explicit UseScratchRegisterScope(MacroAssembler* masm) |
2233 : available_(masm->TmpList()), | 2233 : available_(masm->TmpList()), |
2234 availablefp_(masm->FPTmpList()), | 2234 availablefp_(masm->FPTmpList()), |
2235 old_available_(available_->list()), | 2235 old_available_(available_->list()), |
2236 old_availablefp_(availablefp_->list()) { | 2236 old_availablefp_(availablefp_->list()) { |
2237 ASSERT(available_->type() == CPURegister::kRegister); | 2237 DCHECK(available_->type() == CPURegister::kRegister); |
2238 ASSERT(availablefp_->type() == CPURegister::kFPRegister); | 2238 DCHECK(availablefp_->type() == CPURegister::kFPRegister); |
2239 } | 2239 } |
2240 | 2240 |
2241 ~UseScratchRegisterScope(); | 2241 ~UseScratchRegisterScope(); |
2242 | 2242 |
2243 // Take a register from the appropriate temps list. It will be returned | 2243 // Take a register from the appropriate temps list. It will be returned |
2244 // automatically when the scope ends. | 2244 // automatically when the scope ends. |
2245 Register AcquireW() { return AcquireNextAvailable(available_).W(); } | 2245 Register AcquireW() { return AcquireNextAvailable(available_).W(); } |
2246 Register AcquireX() { return AcquireNextAvailable(available_).X(); } | 2246 Register AcquireX() { return AcquireNextAvailable(available_).X(); } |
2247 FPRegister AcquireS() { return AcquireNextAvailable(availablefp_).S(); } | 2247 FPRegister AcquireS() { return AcquireNextAvailable(availablefp_).S(); } |
2248 FPRegister AcquireD() { return AcquireNextAvailable(availablefp_).D(); } | 2248 FPRegister AcquireD() { return AcquireNextAvailable(availablefp_).D(); } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2332 #error "Unsupported option" | 2332 #error "Unsupported option" |
2333 #define CODE_COVERAGE_STRINGIFY(x) #x | 2333 #define CODE_COVERAGE_STRINGIFY(x) #x |
2334 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) | 2334 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) |
2335 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) | 2335 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) |
2336 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> | 2336 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> |
2337 #else | 2337 #else |
2338 #define ACCESS_MASM(masm) masm-> | 2338 #define ACCESS_MASM(masm) masm-> |
2339 #endif | 2339 #endif |
2340 | 2340 |
2341 #endif // V8_ARM64_MACRO_ASSEMBLER_ARM64_H_ | 2341 #endif // V8_ARM64_MACRO_ASSEMBLER_ARM64_H_ |
OLD | NEW |