diff options
Diffstat (limited to 'deps/v8/src/arm64/macro-assembler-arm64.h')
-rw-r--r-- | deps/v8/src/arm64/macro-assembler-arm64.h | 226 |
1 files changed, 148 insertions, 78 deletions
diff --git a/deps/v8/src/arm64/macro-assembler-arm64.h b/deps/v8/src/arm64/macro-assembler-arm64.h index 7d267a2cb..aa83c7040 100644 --- a/deps/v8/src/arm64/macro-assembler-arm64.h +++ b/deps/v8/src/arm64/macro-assembler-arm64.h @@ -7,10 +7,27 @@ #include <vector> -#include "v8globals.h" -#include "globals.h" +#include "src/globals.h" + +#include "src/arm64/assembler-arm64-inl.h" + +// Simulator specific helpers. +#if USE_SIMULATOR + // TODO(all): If possible automatically prepend an indicator like + // UNIMPLEMENTED or LOCATION. + #define ASM_UNIMPLEMENTED(message) \ + __ Debug(message, __LINE__, NO_PARAM) + #define ASM_UNIMPLEMENTED_BREAK(message) \ + __ Debug(message, __LINE__, \ + FLAG_ignore_asm_unimplemented_break ? NO_PARAM : BREAK) + #define ASM_LOCATION(message) \ + __ Debug("LOCATION: " message, __LINE__, NO_PARAM) +#else + #define ASM_UNIMPLEMENTED(message) + #define ASM_UNIMPLEMENTED_BREAK(message) + #define ASM_LOCATION(message) +#endif -#include "arm64/assembler-arm64-inl.h" namespace v8 { namespace internal { @@ -26,6 +43,11 @@ namespace internal { V(Str, CPURegister&, rt, StoreOpFor(rt)) \ V(Ldrsw, Register&, rt, LDRSW_x) +#define LSPAIR_MACRO_LIST(V) \ + V(Ldp, CPURegister&, rt, rt2, LoadPairOpFor(rt, rt2)) \ + V(Stp, CPURegister&, rt, rt2, StorePairOpFor(rt, rt2)) \ + V(Ldpsw, CPURegister&, rt, rt2, LDPSW_x) + // ---------------------------------------------------------------------------- // Static helper functions @@ -82,7 +104,7 @@ enum BranchType { inline BranchType InvertBranchType(BranchType type) { if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) { return static_cast<BranchType>( - InvertCondition(static_cast<Condition>(type))); + NegateCondition(static_cast<Condition>(type))); } else { return static_cast<BranchType>(type ^ 1); } @@ -90,6 +112,10 @@ inline BranchType InvertBranchType(BranchType type) { enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; +enum PointersToHereCheck { + kPointersToHereMaybeInteresting, + kPointersToHereAreAlwaysInteresting +}; enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved }; enum TargetAddressStorageMode { CAN_INLINE_TARGET_ADDRESS, @@ -199,6 +225,18 @@ class MacroAssembler : public Assembler { static bool IsImmMovz(uint64_t imm, unsigned reg_size); static unsigned CountClearHalfWords(uint64_t imm, unsigned reg_size); + // Try to move an immediate into the destination register in a single + // instruction. Returns true for success, and updates the contents of dst. + // Returns false, otherwise. + bool TryOneInstrMoveImmediate(const Register& dst, int64_t imm); + + // Move an immediate into register dst, and return an Operand object for use + // with a subsequent instruction that accepts a shift. The value moved into + // dst is not necessarily equal to imm; it may have had a shifting operation + // applied to it that will be subsequently undone by the shift applied in the + // Operand. + Operand MoveImmediateForShiftedOp(const Register& dst, int64_t imm); + // Conditional macros. inline void Ccmp(const Register& rn, const Operand& operand, @@ -228,6 +266,14 @@ class MacroAssembler : public Assembler { const MemOperand& addr, LoadStoreOp op); +#define DECLARE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \ + inline void FN(const REGTYPE REG, const REGTYPE REG2, const MemOperand& addr); + LSPAIR_MACRO_LIST(DECLARE_FUNCTION) +#undef DECLARE_FUNCTION + + void LoadStorePairMacro(const CPURegister& rt, const CPURegister& rt2, + const MemOperand& addr, LoadStorePairOp op); + // V8-specific load/store helpers. void Load(const Register& rt, const MemOperand& addr, Representation r); void Store(const Register& rt, const MemOperand& addr, Representation r); @@ -351,7 +397,7 @@ class MacroAssembler : public Assembler { // Provide a template to allow other types to be converted automatically. template<typename T> void Fmov(FPRegister fd, T imm) { - ASSERT(allow_macro_instructions_); + DCHECK(allow_macro_instructions_); Fmov(fd, static_cast<double>(imm)); } inline void Fmov(Register rd, FPRegister fn); @@ -385,19 +431,10 @@ class MacroAssembler : public Assembler { inline void Ldnp(const CPURegister& rt, const CPURegister& rt2, const MemOperand& src); - inline void Ldp(const CPURegister& rt, - const CPURegister& rt2, - const MemOperand& src); - inline void Ldpsw(const Register& rt, - const Register& rt2, - const MemOperand& src); - // Provide both double and float interfaces for FP immediate loads, rather - // than relying on implicit C++ casts. This allows signalling NaNs to be - // preserved when the immediate matches the format of fd. Most systems convert - // signalling NaNs to quiet NaNs when converting between float and double. - inline void Ldr(const FPRegister& ft, double imm); - inline void Ldr(const FPRegister& ft, float imm); - inline void Ldr(const Register& rt, uint64_t imm); + // Load a literal from the inline constant pool. + inline void Ldr(const CPURegister& rt, const Immediate& imm); + // Helper function for double immediate. + inline void Ldr(const CPURegister& rt, double imm); inline void Lsl(const Register& rd, const Register& rn, unsigned shift); inline void Lsl(const Register& rd, const Register& rn, const Register& rm); inline void Lsr(const Register& rd, const Register& rn, unsigned shift); @@ -453,9 +490,6 @@ class MacroAssembler : public Assembler { inline void Stnp(const CPURegister& rt, const CPURegister& rt2, const MemOperand& dst); - inline void Stp(const CPURegister& rt, - const CPURegister& rt2, - const MemOperand& dst); inline void Sxtb(const Register& rd, const Register& rn); inline void Sxth(const Register& rd, const Register& rn); inline void Sxtw(const Register& rd, const Register& rn); @@ -531,6 +565,7 @@ class MacroAssembler : public Assembler { const CPURegister& src6 = NoReg, const CPURegister& src7 = NoReg); void Pop(const CPURegister& dst0, const CPURegister& dst1 = NoReg, const CPURegister& dst2 = NoReg, const CPURegister& dst3 = NoReg); + void Push(const Register& src0, const FPRegister& src1); // Alternative forms of Push and Pop, taking a RegList or CPURegList that // specifies the registers that are to be pushed or popped. Higher-numbered @@ -606,7 +641,7 @@ class MacroAssembler : public Assembler { explicit PushPopQueue(MacroAssembler* masm) : masm_(masm), size_(0) { } ~PushPopQueue() { - ASSERT(queued_.empty()); + DCHECK(queued_.empty()); } void Queue(const CPURegister& rt) { @@ -614,7 +649,11 @@ class MacroAssembler : public Assembler { queued_.push_back(rt); } - void PushQueued(); + enum PreambleDirective { + WITH_PREAMBLE, + SKIP_PREAMBLE + }; + void PushQueued(PreambleDirective preamble_directive = WITH_PREAMBLE); void PopQueued(); private: @@ -718,9 +757,11 @@ class MacroAssembler : public Assembler { // it can be evidence of a potential bug because the ABI forbids accesses // below csp. // - // If emit_debug_code() is false, this emits no code. + // If StackPointer() is the system stack pointer (csp) or ALWAYS_ALIGN_CSP is + // enabled, then csp will be dereferenced to cause the processor + // (or simulator) to abort if it is not properly aligned. // - // If StackPointer() is the system stack pointer, this emits no code. + // If emit_debug_code() is false, this emits no code. void AssertStackConsistency(); // Preserve the callee-saved registers (as defined by AAPCS64). @@ -752,7 +793,7 @@ class MacroAssembler : public Assembler { // Set the current stack pointer, but don't generate any code. inline void SetStackPointer(const Register& stack_pointer) { - ASSERT(!TmpList()->IncludesAliasOf(stack_pointer)); + DCHECK(!TmpList()->IncludesAliasOf(stack_pointer)); sp_ = stack_pointer; } @@ -766,8 +807,8 @@ class MacroAssembler : public Assembler { inline void AlignAndSetCSPForFrame() { int sp_alignment = ActivationFrameAlignment(); // AAPCS64 mandates at least 16-byte alignment. - ASSERT(sp_alignment >= 16); - ASSERT(IsPowerOf2(sp_alignment)); + DCHECK(sp_alignment >= 16); + DCHECK(IsPowerOf2(sp_alignment)); Bic(csp, StackPointer(), sp_alignment - 1); SetStackPointer(csp); } @@ -778,12 +819,22 @@ class MacroAssembler : public Assembler { // // This is necessary when pushing or otherwise adding things to the stack, to // satisfy the AAPCS64 constraint that the memory below the system stack - // pointer is not accessed. + // pointer is not accessed. The amount pushed will be increased as necessary + // to ensure csp remains aligned to 16 bytes. // // This method asserts that StackPointer() is not csp, since the call does // not make sense in that context. inline void BumpSystemStackPointer(const Operand& space); + // Re-synchronizes the system stack pointer (csp) with the current stack + // pointer (according to StackPointer()). This function will ensure the + // new value of the system stack pointer is remains aligned to 16 bytes, and + // is lower than or equal to the value of the current stack pointer. + // + // This method asserts that StackPointer() is not csp, since the call does + // not make sense in that context. + inline void SyncSystemStackPointer(); + // Helpers ------------------------------------------------------------------ // Root register. inline void InitializeRootRegister(); @@ -812,7 +863,7 @@ class MacroAssembler : public Assembler { if (object->IsHeapObject()) { LoadHeapObject(result, Handle<HeapObject>::cast(object)); } else { - ASSERT(object->IsSmi()); + DCHECK(object->IsSmi()); Mov(result, Operand(object)); } } @@ -830,10 +881,15 @@ class MacroAssembler : public Assembler { void NumberOfOwnDescriptors(Register dst, Register map); template<typename Field> - void DecodeField(Register reg) { - static const uint64_t shift = Field::kShift + kSmiShift; + void DecodeField(Register dst, Register src) { + static const uint64_t shift = Field::kShift; static const uint64_t setbits = CountSetBits(Field::kMask, 32); - Ubfx(reg, reg, shift, setbits); + Ubfx(dst, src, shift, setbits); + } + + template<typename Field> + void DecodeField(Register reg) { + DecodeField<Field>(reg, reg); } // ---- SMI and Number Utilities ---- @@ -849,6 +905,10 @@ class MacroAssembler : public Assembler { Register src, UntagMode mode = kNotSpeculativeUntag); + // Tag and push in one step. + inline void SmiTagAndPush(Register src); + inline void SmiTagAndPush(Register src1, Register src2); + // Compute the absolute value of 'smi' and leave the result in 'smi' // register. If 'smi' is the most negative SMI, the absolute value cannot // be represented as a SMI and a jump to 'slow' is done. @@ -907,6 +967,10 @@ class MacroAssembler : public Assembler { // Jump to label if the input double register contains -0.0. void JumpIfMinusZero(DoubleRegister input, Label* on_negative_zero); + // Jump to label if the input integer register contains the double precision + // floating point representation of -0.0. + void JumpIfMinusZero(Register input, Label* on_negative_zero); + // Generate code to do a lookup in the number string cache. If the number in // the register object is found in the cache the generated code falls through // with the result in the result register. The object and the result register @@ -939,7 +1003,7 @@ class MacroAssembler : public Assembler { FPRegister scratch_d, Label* on_successful_conversion = NULL, Label* on_failed_conversion = NULL) { - ASSERT(as_int.Is32Bits()); + DCHECK(as_int.Is32Bits()); TryRepresentDoubleAsInt(as_int, value, scratch_d, on_successful_conversion, on_failed_conversion); } @@ -954,7 +1018,7 @@ class MacroAssembler : public Assembler { FPRegister scratch_d, Label* on_successful_conversion = NULL, Label* on_failed_conversion = NULL) { - ASSERT(as_int.Is64Bits()); + DCHECK(as_int.Is64Bits()); TryRepresentDoubleAsInt(as_int, value, scratch_d, on_successful_conversion, on_failed_conversion); } @@ -1048,15 +1112,6 @@ class MacroAssembler : public Assembler { Register scratch3, Register scratch4); - // Throw a message string as an exception. - void Throw(BailoutReason reason); - - // Throw a message string as an exception if a condition is not true. - void ThrowIf(Condition cond, BailoutReason reason); - - // Throw a message string as an exception if the value is a smi. - void ThrowIfSmi(const Register& value, BailoutReason reason); - void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None()); void TailCallStub(CodeStub* stub); @@ -1351,7 +1406,8 @@ class MacroAssembler : public Assembler { Register scratch1, Register scratch2, CPURegister value = NoFPReg, - CPURegister heap_number_map = NoReg); + CPURegister heap_number_map = NoReg, + MutableMode mode = IMMUTABLE); // --------------------------------------------------------------------------- // Support functions. @@ -1636,7 +1692,8 @@ class MacroAssembler : public Assembler { void ExitFrameRestoreFPRegs(); // Generates function and stub prologue code. - void Prologue(PrologueFrameMode frame_mode); + void StubPrologue(); + void Prologue(bool code_pre_aging); // Enter exit frame. Exit frames are used when calling C code from generated // (JavaScript) code. @@ -1771,7 +1828,9 @@ class MacroAssembler : public Assembler { LinkRegisterStatus lr_status, SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, - SmiCheck smi_check = INLINE_SMI_CHECK); + SmiCheck smi_check = INLINE_SMI_CHECK, + PointersToHereCheck pointers_to_here_check_for_value = + kPointersToHereMaybeInteresting); // As above, but the offset has the tag presubtracted. For use with // MemOperand(reg, off). @@ -1783,7 +1842,9 @@ class MacroAssembler : public Assembler { LinkRegisterStatus lr_status, SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, - SmiCheck smi_check = INLINE_SMI_CHECK) { + SmiCheck smi_check = INLINE_SMI_CHECK, + PointersToHereCheck pointers_to_here_check_for_value = + kPointersToHereMaybeInteresting) { RecordWriteField(context, offset + kHeapObjectTag, value, @@ -1791,9 +1852,17 @@ class MacroAssembler : public Assembler { lr_status, save_fp, remembered_set_action, - smi_check); + smi_check, + pointers_to_here_check_for_value); } + void RecordWriteForMap( + Register object, + Register map, + Register dst, + LinkRegisterStatus lr_status, + SaveFPRegsMode save_fp); + // For a given |object| notify the garbage collector that the slot |address| // has been written. |value| is the object being stored. The value and // address registers are clobbered by the operation. @@ -1804,7 +1873,9 @@ class MacroAssembler : public Assembler { LinkRegisterStatus lr_status, SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, - SmiCheck smi_check = INLINE_SMI_CHECK); + SmiCheck smi_check = INLINE_SMI_CHECK, + PointersToHereCheck pointers_to_here_check_for_value = + kPointersToHereMaybeInteresting); // Checks the color of an object. If the object is already grey or black // then we just fall through, since it is already live. If it is white and @@ -1918,12 +1989,13 @@ class MacroAssembler : public Assembler { // (such as %e, %f or %g) are FPRegisters, and that arguments for integer // placeholders are Registers. // - // A maximum of four arguments may be given to any single Printf call. The - // arguments must be of the same type, but they do not need to have the same - // size. + // At the moment it is only possible to print the value of csp if it is the + // current stack pointer. Otherwise, the MacroAssembler will automatically + // update csp on every push (using BumpSystemStackPointer), so determining its + // value is difficult. // - // The following registers cannot be printed: - // StackPointer(), csp. + // Format placeholders that refer to more than one argument, or to a specific + // argument, are not supported. This includes formats like "%1$d" or "%.*d". // // This function automatically preserves caller-saved registers so that // calling code can use Printf at any point without having to worry about @@ -1931,15 +2003,11 @@ class MacroAssembler : public Assembler { // a problem, preserve the important registers manually and then call // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are // implicitly preserved. - // - // This function assumes (and asserts) that the current stack pointer is - // callee-saved, not caller-saved. This is most likely the case anyway, as a - // caller-saved stack pointer doesn't make a lot of sense. void Printf(const char * format, - const CPURegister& arg0 = NoCPUReg, - const CPURegister& arg1 = NoCPUReg, - const CPURegister& arg2 = NoCPUReg, - const CPURegister& arg3 = NoCPUReg); + CPURegister arg0 = NoCPUReg, + CPURegister arg1 = NoCPUReg, + CPURegister arg2 = NoCPUReg, + CPURegister arg3 = NoCPUReg); // Like Printf, but don't preserve any caller-saved registers, not even 'lr'. // @@ -1993,6 +2061,15 @@ class MacroAssembler : public Assembler { void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0, Register scratch1, Label* found); + // Perform necessary maintenance operations before a push or after a pop. + // + // Note that size is specified in bytes. + void PushPreamble(Operand total_size); + void PopPostamble(Operand total_size); + + void PushPreamble(int count, int size) { PushPreamble(count * size); } + void PopPostamble(int count, int size) { PopPostamble(count * size); } + private: // Helpers for CopyFields. // These each implement CopyFields in a different way. @@ -2020,22 +2097,15 @@ class MacroAssembler : public Assembler { const CPURegister& dst0, const CPURegister& dst1, const CPURegister& dst2, const CPURegister& dst3); - // Perform necessary maintenance operations before a push or pop. - // - // Note that size is specified in bytes. - void PrepareForPush(Operand total_size); - void PrepareForPop(Operand total_size); - - void PrepareForPush(int count, int size) { PrepareForPush(count * size); } - void PrepareForPop(int count, int size) { PrepareForPop(count * size); } - // Call Printf. On a native build, a simple call will be generated, but if the // simulator is being used then a suitable pseudo-instruction is used. The // arguments and stack (csp) must be prepared by the caller as for a normal // AAPCS64 call to 'printf'. // - // The 'type' argument specifies the type of the optional arguments. - void CallPrintf(CPURegister::RegisterType type = CPURegister::kNoRegister); + // The 'args' argument should point to an array of variable arguments in their + // proper PCS registers (and in calling order). The argument registers can + // have mixed types. The format string (x0) should not be included. + void CallPrintf(int arg_count = 0, const CPURegister * args = NULL); // Helper for throwing exceptions. Compute a handler address and jump to // it. See the implementation for register usage. @@ -2131,7 +2201,7 @@ class MacroAssembler : public Assembler { // emitted is what you specified when creating the scope. class InstructionAccurateScope BASE_EMBEDDED { public: - InstructionAccurateScope(MacroAssembler* masm, size_t count = 0) + explicit InstructionAccurateScope(MacroAssembler* masm, size_t count = 0) : masm_(masm) #ifdef DEBUG , @@ -2156,7 +2226,7 @@ class InstructionAccurateScope BASE_EMBEDDED { masm_->EndBlockPools(); #ifdef DEBUG if (start_.is_bound()) { - ASSERT(masm_->SizeOfCodeGeneratedSince(&start_) == size_); + DCHECK(masm_->SizeOfCodeGeneratedSince(&start_) == size_); } masm_->set_allow_macro_instructions(previous_allow_macro_instructions_); #endif @@ -2186,8 +2256,8 @@ class UseScratchRegisterScope { availablefp_(masm->FPTmpList()), old_available_(available_->list()), old_availablefp_(availablefp_->list()) { - ASSERT(available_->type() == CPURegister::kRegister); - ASSERT(availablefp_->type() == CPURegister::kFPRegister); + DCHECK(available_->type() == CPURegister::kRegister); + DCHECK(availablefp_->type() == CPURegister::kFPRegister); } ~UseScratchRegisterScope(); |