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
3 // found in the LICENSE file.
5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_
6 #define V8_ARM64_ASSEMBLER_ARM64_H_
13 #include "src/arm64/instructions-arm64.h"
14 #include "src/assembler.h"
15 #include "src/compiler.h"
16 #include "src/globals.h"
17 #include "src/utils.h"
24 // -----------------------------------------------------------------------------
26 #define REGISTER_CODE_LIST(R) \
27 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
28 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
29 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
30 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
33 static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
36 // Some CPURegister methods can return Register and FPRegister types, so we
37 // need to declare them in advance.
44 // The kInvalid value is used to detect uninitialized static instances,
45 // which are always zero-initialized before any constructors are called.
52 static CPURegister Create(unsigned code, unsigned size, RegisterType type) {
53 CPURegister r = {code, size, type};
57 unsigned code() const;
58 RegisterType type() const;
60 unsigned SizeInBits() const;
61 int SizeInBytes() const;
62 bool Is32Bits() const;
63 bool Is64Bits() const;
65 bool IsValidOrNone() const;
66 bool IsValidRegister() const;
67 bool IsValidFPRegister() const;
69 bool Is(const CPURegister& other) const;
70 bool Aliases(const CPURegister& other) const;
75 bool IsRegister() const;
76 bool IsFPRegister() const;
83 bool IsSameSizeAndType(const CPURegister& other) const;
86 bool is(const CPURegister& other) const { return Is(other); }
87 bool is_valid() const { return IsValid(); }
91 RegisterType reg_type;
95 struct Register : public CPURegister {
96 static Register Create(unsigned code, unsigned size) {
97 return Register(CPURegister::Create(code, size, CPURegister::kRegister));
103 reg_type = CPURegister::kNoRegister;
106 explicit Register(const CPURegister& r) {
107 reg_code = r.reg_code;
108 reg_size = r.reg_size;
109 reg_type = r.reg_type;
110 DCHECK(IsValidOrNone());
113 Register(const Register& r) { // NOLINT(runtime/explicit)
114 reg_code = r.reg_code;
115 reg_size = r.reg_size;
116 reg_type = r.reg_type;
117 DCHECK(IsValidOrNone());
120 bool IsValid() const {
121 DCHECK(IsRegister() || IsNone());
122 return IsValidRegister();
125 static Register XRegFromCode(unsigned code);
126 static Register WRegFromCode(unsigned code);
128 // Start of V8 compatibility section ---------------------
129 // These memebers are necessary for compilation.
130 // A few of them may be unused for now.
132 static const int kNumRegisters = kNumberOfRegisters;
133 static int NumRegisters() { return kNumRegisters; }
135 // We allow crankshaft to use the following registers:
138 // - x27 (also context)
140 // TODO(all): Register x25 is currently free and could be available for
141 // crankshaft, but we don't use it as we might use it as a per function
142 // literal pool pointer in the future.
144 // TODO(all): Consider storing cp in x25 to have only two ranges.
145 // We split allocatable registers in three ranges called
149 static const unsigned kAllocatableLowRangeBegin = 0;
150 static const unsigned kAllocatableLowRangeEnd = 15;
151 static const unsigned kAllocatableHighRangeBegin = 18;
152 static const unsigned kAllocatableHighRangeEnd = 24;
153 static const unsigned kAllocatableContext = 27;
155 // Gap between low and high ranges.
156 static const int kAllocatableRangeGapSize =
157 (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
159 static const int kMaxNumAllocatableRegisters =
160 (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
161 (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1) + 1; // cp
162 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
164 // Return true if the register is one that crankshaft can allocate.
165 bool IsAllocatable() const {
166 return ((reg_code == kAllocatableContext) ||
167 (reg_code <= kAllocatableLowRangeEnd) ||
168 ((reg_code >= kAllocatableHighRangeBegin) &&
169 (reg_code <= kAllocatableHighRangeEnd)));
172 static Register FromAllocationIndex(unsigned index) {
173 DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters()));
174 // cp is the last allocatable register.
175 if (index == (static_cast<unsigned>(NumAllocatableRegisters() - 1))) {
176 return from_code(kAllocatableContext);
179 // Handle low and high ranges.
180 return (index <= kAllocatableLowRangeEnd)
182 : from_code(index + kAllocatableRangeGapSize);
185 static const char* AllocationIndexToString(int index) {
186 DCHECK((index >= 0) && (index < NumAllocatableRegisters()));
187 DCHECK((kAllocatableLowRangeBegin == 0) &&
188 (kAllocatableLowRangeEnd == 15) &&
189 (kAllocatableHighRangeBegin == 18) &&
190 (kAllocatableHighRangeEnd == 24) &&
191 (kAllocatableContext == 27));
192 const char* const names[] = {
193 "x0", "x1", "x2", "x3", "x4",
194 "x5", "x6", "x7", "x8", "x9",
195 "x10", "x11", "x12", "x13", "x14",
196 "x15", "x18", "x19", "x20", "x21",
197 "x22", "x23", "x24", "x27",
202 static int ToAllocationIndex(Register reg) {
203 DCHECK(reg.IsAllocatable());
204 unsigned code = reg.code();
205 if (code == kAllocatableContext) {
206 return NumAllocatableRegisters() - 1;
209 return (code <= kAllocatableLowRangeEnd)
211 : code - kAllocatableRangeGapSize;
214 static Register from_code(int code) {
215 // Always return an X register.
216 return Register::Create(code, kXRegSizeInBits);
219 // End of V8 compatibility section -----------------------
223 struct FPRegister : public CPURegister {
224 static FPRegister Create(unsigned code, unsigned size) {
226 CPURegister::Create(code, size, CPURegister::kFPRegister));
232 reg_type = CPURegister::kNoRegister;
235 explicit FPRegister(const CPURegister& r) {
236 reg_code = r.reg_code;
237 reg_size = r.reg_size;
238 reg_type = r.reg_type;
239 DCHECK(IsValidOrNone());
242 FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit)
243 reg_code = r.reg_code;
244 reg_size = r.reg_size;
245 reg_type = r.reg_type;
246 DCHECK(IsValidOrNone());
249 bool IsValid() const {
250 DCHECK(IsFPRegister() || IsNone());
251 return IsValidFPRegister();
254 static FPRegister SRegFromCode(unsigned code);
255 static FPRegister DRegFromCode(unsigned code);
257 // Start of V8 compatibility section ---------------------
258 static const int kMaxNumRegisters = kNumberOfFPRegisters;
260 // Crankshaft can use all the FP registers except:
261 // - d15 which is used to keep the 0 double value
262 // - d30 which is used in crankshaft as a double scratch register
263 // - d31 which is used in the MacroAssembler as a double scratch register
264 static const unsigned kAllocatableLowRangeBegin = 0;
265 static const unsigned kAllocatableLowRangeEnd = 14;
266 static const unsigned kAllocatableHighRangeBegin = 16;
267 static const unsigned kAllocatableHighRangeEnd = 28;
269 static const RegList kAllocatableFPRegisters = 0x1fff7fff;
271 // Gap between low and high ranges.
272 static const int kAllocatableRangeGapSize =
273 (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
275 static const int kMaxNumAllocatableRegisters =
276 (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
277 (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1);
278 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
280 // TODO(turbofan): Proper float32 support.
281 static int NumAllocatableAliasedRegisters() {
282 return NumAllocatableRegisters();
285 // Return true if the register is one that crankshaft can allocate.
286 bool IsAllocatable() const {
287 return (Bit() & kAllocatableFPRegisters) != 0;
290 static FPRegister FromAllocationIndex(unsigned int index) {
291 DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters()));
293 return (index <= kAllocatableLowRangeEnd)
295 : from_code(index + kAllocatableRangeGapSize);
298 static const char* AllocationIndexToString(int index) {
299 DCHECK((index >= 0) && (index < NumAllocatableRegisters()));
300 DCHECK((kAllocatableLowRangeBegin == 0) &&
301 (kAllocatableLowRangeEnd == 14) &&
302 (kAllocatableHighRangeBegin == 16) &&
303 (kAllocatableHighRangeEnd == 28));
304 const char* const names[] = {
305 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
306 "d8", "d9", "d10", "d11", "d12", "d13", "d14",
307 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
308 "d24", "d25", "d26", "d27", "d28"
313 static int ToAllocationIndex(FPRegister reg) {
314 DCHECK(reg.IsAllocatable());
315 unsigned code = reg.code();
317 return (code <= kAllocatableLowRangeEnd)
319 : code - kAllocatableRangeGapSize;
322 static FPRegister from_code(int code) {
323 // Always return a D register.
324 return FPRegister::Create(code, kDRegSizeInBits);
326 // End of V8 compatibility section -----------------------
330 STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register));
331 STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister));
334 #if defined(ARM64_DEFINE_REG_STATICS)
335 #define INITIALIZE_REGISTER(register_class, name, code, size, type) \
336 const CPURegister init_##register_class##_##name = {code, size, type}; \
337 const register_class& name = *reinterpret_cast<const register_class*>( \
338 &init_##register_class##_##name)
339 #define ALIAS_REGISTER(register_class, alias, name) \
340 const register_class& alias = *reinterpret_cast<const register_class*>( \
341 &init_##register_class##_##name)
343 #define INITIALIZE_REGISTER(register_class, name, code, size, type) \
344 extern const register_class& name
345 #define ALIAS_REGISTER(register_class, alias, name) \
346 extern const register_class& alias
347 #endif // defined(ARM64_DEFINE_REG_STATICS)
349 // No*Reg is used to indicate an unused argument, or an error case. Note that
350 // these all compare equal (using the Is() method). The Register and FPRegister
351 // variants are provided for convenience.
352 INITIALIZE_REGISTER(Register, NoReg, 0, 0, CPURegister::kNoRegister);
353 INITIALIZE_REGISTER(FPRegister, NoFPReg, 0, 0, CPURegister::kNoRegister);
354 INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister);
357 INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister);
359 #define DEFINE_REGISTERS(N) \
360 INITIALIZE_REGISTER(Register, w##N, N, \
361 kWRegSizeInBits, CPURegister::kRegister); \
362 INITIALIZE_REGISTER(Register, x##N, N, \
363 kXRegSizeInBits, CPURegister::kRegister);
364 REGISTER_CODE_LIST(DEFINE_REGISTERS)
365 #undef DEFINE_REGISTERS
367 INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits,
368 CPURegister::kRegister);
369 INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits,
370 CPURegister::kRegister);
372 #define DEFINE_FPREGISTERS(N) \
373 INITIALIZE_REGISTER(FPRegister, s##N, N, \
374 kSRegSizeInBits, CPURegister::kFPRegister); \
375 INITIALIZE_REGISTER(FPRegister, d##N, N, \
376 kDRegSizeInBits, CPURegister::kFPRegister);
377 REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
378 #undef DEFINE_FPREGISTERS
380 #undef INITIALIZE_REGISTER
382 // Registers aliases.
383 ALIAS_REGISTER(Register, ip0, x16);
384 ALIAS_REGISTER(Register, ip1, x17);
385 ALIAS_REGISTER(Register, wip0, w16);
386 ALIAS_REGISTER(Register, wip1, w17);
388 ALIAS_REGISTER(Register, root, x26);
389 ALIAS_REGISTER(Register, rr, x26);
390 // Context pointer register.
391 ALIAS_REGISTER(Register, cp, x27);
392 // We use a register as a JS stack pointer to overcome the restriction on the
393 // architectural SP alignment.
394 // We chose x28 because it is contiguous with the other specific purpose
396 STATIC_ASSERT(kJSSPCode == 28);
397 ALIAS_REGISTER(Register, jssp, x28);
398 ALIAS_REGISTER(Register, wjssp, w28);
399 ALIAS_REGISTER(Register, fp, x29);
400 ALIAS_REGISTER(Register, lr, x30);
401 ALIAS_REGISTER(Register, xzr, x31);
402 ALIAS_REGISTER(Register, wzr, w31);
404 // Keeps the 0 double value.
405 ALIAS_REGISTER(FPRegister, fp_zero, d15);
406 // Crankshaft double scratch register.
407 ALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d29);
408 // MacroAssembler double scratch registers.
409 ALIAS_REGISTER(FPRegister, fp_scratch, d30);
410 ALIAS_REGISTER(FPRegister, fp_scratch1, d30);
411 ALIAS_REGISTER(FPRegister, fp_scratch2, d31);
413 #undef ALIAS_REGISTER
416 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1,
417 Register reg2 = NoReg,
418 Register reg3 = NoReg,
419 Register reg4 = NoReg);
422 // AreAliased returns true if any of the named registers overlap. Arguments set
423 // to NoReg are ignored. The system stack pointer may be specified.
424 bool AreAliased(const CPURegister& reg1,
425 const CPURegister& reg2,
426 const CPURegister& reg3 = NoReg,
427 const CPURegister& reg4 = NoReg,
428 const CPURegister& reg5 = NoReg,
429 const CPURegister& reg6 = NoReg,
430 const CPURegister& reg7 = NoReg,
431 const CPURegister& reg8 = NoReg);
433 // AreSameSizeAndType returns true if all of the specified registers have the
434 // same size, and are of the same type. The system stack pointer may be
435 // specified. Arguments set to NoReg are ignored, as are any subsequent
436 // arguments. At least one argument (reg1) must be valid (not NoCPUReg).
437 bool AreSameSizeAndType(const CPURegister& reg1,
438 const CPURegister& reg2,
439 const CPURegister& reg3 = NoCPUReg,
440 const CPURegister& reg4 = NoCPUReg,
441 const CPURegister& reg5 = NoCPUReg,
442 const CPURegister& reg6 = NoCPUReg,
443 const CPURegister& reg7 = NoCPUReg,
444 const CPURegister& reg8 = NoCPUReg);
447 typedef FPRegister DoubleRegister;
450 // -----------------------------------------------------------------------------
451 // Lists of registers.
454 explicit CPURegList(CPURegister reg1,
455 CPURegister reg2 = NoCPUReg,
456 CPURegister reg3 = NoCPUReg,
457 CPURegister reg4 = NoCPUReg)
458 : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()),
459 size_(reg1.SizeInBits()), type_(reg1.type()) {
460 DCHECK(AreSameSizeAndType(reg1, reg2, reg3, reg4));
464 CPURegList(CPURegister::RegisterType type, unsigned size, RegList list)
465 : list_(list), size_(size), type_(type) {
469 CPURegList(CPURegister::RegisterType type, unsigned size,
470 unsigned first_reg, unsigned last_reg)
471 : size_(size), type_(type) {
472 DCHECK(((type == CPURegister::kRegister) &&
473 (last_reg < kNumberOfRegisters)) ||
474 ((type == CPURegister::kFPRegister) &&
475 (last_reg < kNumberOfFPRegisters)));
476 DCHECK(last_reg >= first_reg);
477 list_ = (1UL << (last_reg + 1)) - 1;
478 list_ &= ~((1UL << first_reg) - 1);
482 CPURegister::RegisterType type() const {
487 RegList list() const {
492 inline void set_list(RegList new_list) {
497 // Combine another CPURegList into this one. Registers that already exist in
498 // this list are left unchanged. The type and size of the registers in the
499 // 'other' list must match those in this list.
500 void Combine(const CPURegList& other);
502 // Remove every register in the other CPURegList from this one. Registers that
503 // do not exist in this list are ignored. The type of the registers in the
504 // 'other' list must match those in this list.
505 void Remove(const CPURegList& other);
507 // Variants of Combine and Remove which take CPURegisters.
508 void Combine(const CPURegister& other);
509 void Remove(const CPURegister& other1,
510 const CPURegister& other2 = NoCPUReg,
511 const CPURegister& other3 = NoCPUReg,
512 const CPURegister& other4 = NoCPUReg);
514 // Variants of Combine and Remove which take a single register by its code;
515 // the type and size of the register is inferred from this list.
516 void Combine(int code);
517 void Remove(int code);
519 // Remove all callee-saved registers from the list. This can be useful when
520 // preparing registers for an AAPCS64 function call, for example.
521 void RemoveCalleeSaved();
523 CPURegister PopLowestIndex();
524 CPURegister PopHighestIndex();
526 // AAPCS64 callee-saved registers.
527 static CPURegList GetCalleeSaved(unsigned size = kXRegSizeInBits);
528 static CPURegList GetCalleeSavedFP(unsigned size = kDRegSizeInBits);
530 // AAPCS64 caller-saved registers. Note that this includes lr.
531 static CPURegList GetCallerSaved(unsigned size = kXRegSizeInBits);
532 static CPURegList GetCallerSavedFP(unsigned size = kDRegSizeInBits);
534 // Registers saved as safepoints.
535 static CPURegList GetSafepointSavedRegisters();
537 bool IsEmpty() const {
542 bool IncludesAliasOf(const CPURegister& other1,
543 const CPURegister& other2 = NoCPUReg,
544 const CPURegister& other3 = NoCPUReg,
545 const CPURegister& other4 = NoCPUReg) const {
548 if (!other1.IsNone() && (other1.type() == type_)) list |= other1.Bit();
549 if (!other2.IsNone() && (other2.type() == type_)) list |= other2.Bit();
550 if (!other3.IsNone() && (other3.type() == type_)) list |= other3.Bit();
551 if (!other4.IsNone() && (other4.type() == type_)) list |= other4.Bit();
552 return (list_ & list) != 0;
557 return CountSetBits(list_, kRegListSizeInBits);
560 unsigned RegisterSizeInBits() const {
565 unsigned RegisterSizeInBytes() const {
566 int size_in_bits = RegisterSizeInBits();
567 DCHECK((size_in_bits % kBitsPerByte) == 0);
568 return size_in_bits / kBitsPerByte;
571 unsigned TotalSizeInBytes() const {
573 return RegisterSizeInBytes() * Count();
579 CPURegister::RegisterType type_;
581 bool IsValid() const {
582 const RegList kValidRegisters = 0x8000000ffffffff;
583 const RegList kValidFPRegisters = 0x0000000ffffffff;
585 case CPURegister::kRegister:
586 return (list_ & kValidRegisters) == list_;
587 case CPURegister::kFPRegister:
588 return (list_ & kValidFPRegisters) == list_;
589 case CPURegister::kNoRegister:
599 // AAPCS64 callee-saved registers.
600 #define kCalleeSaved CPURegList::GetCalleeSaved()
601 #define kCalleeSavedFP CPURegList::GetCalleeSavedFP()
604 // AAPCS64 caller-saved registers. Note that this includes lr.
605 #define kCallerSaved CPURegList::GetCallerSaved()
606 #define kCallerSavedFP CPURegList::GetCallerSavedFP()
608 // -----------------------------------------------------------------------------
613 inline explicit Immediate(Handle<T> handle);
615 // This is allowed to be an implicit constructor because Immediate is
616 // a wrapper class that doesn't normally perform any type conversion.
618 inline Immediate(T value); // NOLINT(runtime/explicit)
621 inline Immediate(T value, RelocInfo::Mode rmode);
623 int64_t value() const { return value_; }
624 RelocInfo::Mode rmode() const { return rmode_; }
627 void InitializeHandle(Handle<Object> value);
630 RelocInfo::Mode rmode_;
634 // -----------------------------------------------------------------------------
636 const int kSmiShift = kSmiTagSize + kSmiShiftSize;
637 const uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
639 // Represents an operand in a machine instruction.
641 // TODO(all): If necessary, study more in details which methods
642 // TODO(all): should be inlined or not.
644 // rm, {<shift> {#<shift_amount>}}
645 // where <shift> is one of {LSL, LSR, ASR, ROR}.
646 // <shift_amount> is uint6_t.
647 // This is allowed to be an implicit constructor because Operand is
648 // a wrapper class that doesn't normally perform any type conversion.
649 inline Operand(Register reg,
651 unsigned shift_amount = 0); // NOLINT(runtime/explicit)
653 // rm, <extend> {#<shift_amount>}
654 // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}.
655 // <shift_amount> is uint2_t.
656 inline Operand(Register reg,
658 unsigned shift_amount = 0);
661 inline explicit Operand(Handle<T> handle);
663 // Implicit constructor for all int types, ExternalReference, and Smi.
665 inline Operand(T t); // NOLINT(runtime/explicit)
667 // Implicit constructor for int types.
669 inline Operand(T t, RelocInfo::Mode rmode);
671 inline bool IsImmediate() const;
672 inline bool IsShiftedRegister() const;
673 inline bool IsExtendedRegister() const;
674 inline bool IsZero() const;
676 // This returns an LSL shift (<= 4) operand as an equivalent extend operand,
677 // which helps in the encoding of instructions that use the stack pointer.
678 inline Operand ToExtendedRegister() const;
680 inline Immediate immediate() const;
681 inline int64_t ImmediateValue() const;
682 inline Register reg() const;
683 inline Shift shift() const;
684 inline Extend extend() const;
685 inline unsigned shift_amount() const;
687 // Relocation information.
688 bool NeedsRelocation(const Assembler* assembler) const;
691 inline static Operand UntagSmi(Register smi);
692 inline static Operand UntagSmiAndScale(Register smi, int scale);
695 Immediate immediate_;
699 unsigned shift_amount_;
703 // MemOperand represents a memory operand in a load or store instruction.
707 inline explicit MemOperand(Register base,
709 AddrMode addrmode = Offset);
710 inline explicit MemOperand(Register base,
713 unsigned shift_amount = 0);
714 inline explicit MemOperand(Register base,
717 unsigned shift_amount = 0);
718 inline explicit MemOperand(Register base,
719 const Operand& offset,
720 AddrMode addrmode = Offset);
722 const Register& base() const { return base_; }
723 const Register& regoffset() const { return regoffset_; }
724 int64_t offset() const { return offset_; }
725 AddrMode addrmode() const { return addrmode_; }
726 Shift shift() const { return shift_; }
727 Extend extend() const { return extend_; }
728 unsigned shift_amount() const { return shift_amount_; }
729 inline bool IsImmediateOffset() const;
730 inline bool IsRegisterOffset() const;
731 inline bool IsPreIndex() const;
732 inline bool IsPostIndex() const;
734 // For offset modes, return the offset as an Operand. This helper cannot
735 // handle indexed modes.
736 inline Operand OffsetAsOperand() const;
739 kNotPair, // Can't use a pair instruction.
740 kPairAB, // Can use a pair instruction (operandA has lower address).
741 kPairBA // Can use a pair instruction (operandB has lower address).
743 // Check if two MemOperand are consistent for stp/ldp use.
744 static PairResult AreConsistentForPair(const MemOperand& operandA,
745 const MemOperand& operandB,
746 int access_size_log2 = kXRegSizeLog2);
755 unsigned shift_amount_;
761 explicit ConstPool(Assembler* assm)
764 shared_entries_count(0) {}
765 void RecordEntry(intptr_t data, RelocInfo::Mode mode);
766 int EntryCount() const {
767 return shared_entries_count + unique_entries_.size();
769 bool IsEmpty() const {
770 return shared_entries_.empty() && unique_entries_.empty();
772 // Distance in bytes between the current pc and the first instruction
773 // using the pool. If there are no pending entries return kMaxInt.
774 int DistanceToFirstUse();
775 // Offset after which instructions using the pool will be out of range.
777 // Maximum size the constant pool can be with current entries. It always
778 // includes alignment padding and branch over.
780 // Size in bytes of the literal pool *if* it is emitted at the current
781 // pc. The size will include the branch over the pool if it was requested.
782 int SizeIfEmittedAtCurrentPc(bool require_jump);
783 // Emit the literal pool at the current pc with a branch over the pool if
785 void Emit(bool require_jump);
786 // Discard any pending pool entries.
790 bool CanBeShared(RelocInfo::Mode mode);
796 // Keep track of the first instruction requiring a constant pool entry
797 // since the previous constant pool was emitted.
799 // values, pc offset(s) of entries which can be shared.
800 std::multimap<uint64_t, int> shared_entries_;
801 // Number of distinct literal in shared entries.
802 int shared_entries_count;
803 // values, pc offset of entries which cannot be shared.
804 std::vector<std::pair<uint64_t, int> > unique_entries_;
808 // -----------------------------------------------------------------------------
811 class Assembler : public AssemblerBase {
813 // Create an assembler. Instructions and relocation information are emitted
814 // into a buffer, with the instructions starting from the beginning and the
815 // relocation information starting from the end of the buffer. See CodeDesc
816 // for a detailed comment on the layout (globals.h).
818 // If the provided buffer is NULL, the assembler allocates and grows its own
819 // buffer, and buffer_size determines the initial buffer size. The buffer is
820 // owned by the assembler and deallocated upon destruction of the assembler.
822 // If the provided buffer is not NULL, the assembler uses the provided buffer
823 // for code generation and assumes its size to be buffer_size. If the buffer
824 // is too small, a fatal error occurs. No deallocation of the buffer is done
825 // upon destruction of the assembler.
826 Assembler(Isolate* arg_isolate, void* buffer, int buffer_size);
828 virtual ~Assembler();
830 virtual void AbortedCodeGeneration() {
834 // System functions ---------------------------------------------------------
835 // Start generating code from the beginning of the buffer, discarding any code
836 // and data that has already been emitted into the buffer.
838 // In order to avoid any accidental transfer of state, Reset DCHECKs that the
839 // constant pool is not blocked.
842 // GetCode emits any pending (non-emitted) code and fills the descriptor
843 // desc. GetCode() is idempotent; it returns the same result if no other
844 // Assembler functions are invoked in between GetCode() calls.
846 // The descriptor (desc) can be NULL. In that case, the code is finalized as
847 // usual, but the descriptor is not populated.
848 void GetCode(CodeDesc* desc);
850 // Insert the smallest number of nop instructions
851 // possible to align the pc offset to a multiple
852 // of m. m must be a power of 2 (>= 4).
855 inline void Unreachable();
857 // Label --------------------------------------------------------------------
858 // Bind a label to the current pc. Note that labels can only be bound once,
859 // and if labels are linked to other instructions, they _must_ be bound
860 // before they go out of scope.
861 void bind(Label* label);
864 // RelocInfo and pools ------------------------------------------------------
866 // Record relocation information for current pc_.
867 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
869 // Return the address in the constant pool of the code target address used by
870 // the branch/call instruction at pc.
871 inline static Address target_pointer_address_at(Address pc);
873 // Read/Modify the code target address in the branch/call instruction at pc.
874 inline static Address target_address_at(Address pc,
875 ConstantPoolArray* constant_pool);
876 inline static void set_target_address_at(Address pc,
877 ConstantPoolArray* constant_pool,
879 ICacheFlushMode icache_flush_mode =
880 FLUSH_ICACHE_IF_NEEDED);
881 static inline Address target_address_at(Address pc, Code* code);
882 static inline void set_target_address_at(Address pc,
885 ICacheFlushMode icache_flush_mode =
886 FLUSH_ICACHE_IF_NEEDED);
888 // Return the code target address at a call site from the return address of
889 // that call in the instruction stream.
890 inline static Address target_address_from_return_address(Address pc);
892 // Given the address of the beginning of a call, return the address in the
893 // instruction stream that call will return from.
894 inline static Address return_address_from_call_start(Address pc);
896 // Return the code target address of the patch debug break slot
897 inline static Address break_address_from_return_address(Address pc);
899 // This sets the branch destination (which is in the constant pool on ARM).
900 // This is for calls and branches within generated code.
901 inline static void deserialization_set_special_target_at(
902 Address constant_pool_entry, Code* code, Address target);
904 // This sets the internal reference at the pc.
905 inline static void deserialization_set_target_internal_reference_at(
906 Address pc, Address target,
907 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
909 // All addresses in the constant pool are the same size as pointers.
910 static const int kSpecialTargetSize = kPointerSize;
912 // The sizes of the call sequences emitted by MacroAssembler::Call.
913 // Wherever possible, use MacroAssembler::CallSize instead of these constants,
914 // as it will choose the correct value for a given relocation mode.
916 // Without relocation:
917 // movz temp, #(target & 0x000000000000ffff)
918 // movk temp, #(target & 0x00000000ffff0000)
919 // movk temp, #(target & 0x0000ffff00000000)
925 static const int kCallSizeWithoutRelocation = 4 * kInstructionSize;
926 static const int kCallSizeWithRelocation = 2 * kInstructionSize;
928 // Size of the generated code in bytes
929 uint64_t SizeOfGeneratedCode() const {
930 DCHECK((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_)));
931 return pc_ - buffer_;
934 // Return the code size generated from label to the current position.
935 uint64_t SizeOfCodeGeneratedSince(const Label* label) {
936 DCHECK(label->is_bound());
937 DCHECK(pc_offset() >= label->pos());
938 DCHECK(pc_offset() < buffer_size_);
939 return pc_offset() - label->pos();
942 // Check the size of the code generated since the given label. This function
943 // is used primarily to work around comparisons between signed and unsigned
944 // quantities, since V8 uses both.
945 // TODO(jbramley): Work out what sign to use for these things and if possible,
946 // change things to be consistent.
947 void AssertSizeOfCodeGeneratedSince(const Label* label, ptrdiff_t size) {
949 DCHECK(static_cast<uint64_t>(size) == SizeOfCodeGeneratedSince(label));
952 // Return the number of instructions generated from label to the
954 int InstructionsGeneratedSince(const Label* label) {
955 return SizeOfCodeGeneratedSince(label) / kInstructionSize;
958 // Number of instructions generated for the return sequence in
959 // FullCodeGenerator::EmitReturnSequence.
960 static const int kJSReturnSequenceInstructions = 7;
961 static const int kJSReturnSequenceLength =
962 kJSReturnSequenceInstructions * kInstructionSize;
963 // Distance between start of patched return sequence and the emitted address
965 static const int kPatchReturnSequenceAddressOffset = 0;
966 static const int kPatchDebugBreakSlotAddressOffset = 0;
968 // Number of instructions necessary to be able to later patch it to a call.
969 // See DebugCodegen::GenerateSlot() and
970 // BreakLocation::SetDebugBreakAtSlot().
971 static const int kDebugBreakSlotInstructions = 4;
972 static const int kDebugBreakSlotLength =
973 kDebugBreakSlotInstructions * kInstructionSize;
975 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstructionSize;
977 // Prevent contant pool emission until EndBlockConstPool is called.
978 // Call to this function can be nested but must be followed by an equal
979 // number of call to EndBlockConstpool.
980 void StartBlockConstPool();
982 // Resume constant pool emission. Need to be called as many time as
983 // StartBlockConstPool to have an effect.
984 void EndBlockConstPool();
986 bool is_const_pool_blocked() const;
987 static bool IsConstantPoolAt(Instruction* instr);
988 static int ConstantPoolSizeAt(Instruction* instr);
989 // See Assembler::CheckConstPool for more info.
990 void EmitPoolGuard();
992 // Prevent veneer pool emission until EndBlockVeneerPool is called.
993 // Call to this function can be nested but must be followed by an equal
994 // number of call to EndBlockConstpool.
995 void StartBlockVeneerPool();
997 // Resume constant pool emission. Need to be called as many time as
998 // StartBlockVeneerPool to have an effect.
999 void EndBlockVeneerPool();
1001 bool is_veneer_pool_blocked() const {
1002 return veneer_pool_blocked_nesting_ > 0;
1005 // Block/resume emission of constant pools and veneer pools.
1006 void StartBlockPools() {
1007 StartBlockConstPool();
1008 StartBlockVeneerPool();
1010 void EndBlockPools() {
1011 EndBlockConstPool();
1012 EndBlockVeneerPool();
1015 // Debugging ----------------------------------------------------------------
1016 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1017 void RecordComment(const char* msg);
1019 // Record a deoptimization reason that can be used by a log or cpu profiler.
1020 // Use --trace-deopt to enable.
1021 void RecordDeoptReason(const int reason, const SourcePosition position);
1023 int buffer_space() const;
1025 // Mark address of the ExitJSFrame code.
1026 void RecordJSReturn();
1028 // Mark address of a debug break slot.
1029 void RecordDebugBreakSlot();
1031 // Record the emission of a constant pool.
1033 // The emission of constant and veneer pools depends on the size of the code
1034 // generated and the number of RelocInfo recorded.
1035 // The Debug mechanism needs to map code offsets between two versions of a
1036 // function, compiled with and without debugger support (see for example
1037 // Debug::PrepareForBreakPoints()).
1038 // Compiling functions with debugger support generates additional code
1039 // (DebugCodegen::GenerateSlot()). This may affect the emission of the pools
1040 // and cause the version of the code with debugger support to have pools
1041 // generated in different places.
1042 // Recording the position and size of emitted pools allows to correctly
1043 // compute the offset mappings between the different versions of a function in
1046 // The parameter indicates the size of the pool (in bytes), including
1047 // the marker and branch over the data.
1048 void RecordConstPool(int size);
1051 // Instruction set functions ------------------------------------------------
1053 // Branch / Jump instructions.
1054 // For branches offsets are scaled, i.e. they in instrcutions not in bytes.
1055 // Branch to register.
1056 void br(const Register& xn);
1058 // Branch-link to register.
1059 void blr(const Register& xn);
1061 // Branch to register with return hint.
1062 void ret(const Register& xn = lr);
1064 // Unconditional branch to label.
1065 void b(Label* label);
1067 // Conditional branch to label.
1068 void b(Label* label, Condition cond);
1070 // Unconditional branch to PC offset.
1073 // Conditional branch to PC offset.
1074 void b(int imm19, Condition cond);
1076 // Branch-link to label / pc offset.
1077 void bl(Label* label);
1080 // Compare and branch to label / pc offset if zero.
1081 void cbz(const Register& rt, Label* label);
1082 void cbz(const Register& rt, int imm19);
1084 // Compare and branch to label / pc offset if not zero.
1085 void cbnz(const Register& rt, Label* label);
1086 void cbnz(const Register& rt, int imm19);
1088 // Test bit and branch to label / pc offset if zero.
1089 void tbz(const Register& rt, unsigned bit_pos, Label* label);
1090 void tbz(const Register& rt, unsigned bit_pos, int imm14);
1092 // Test bit and branch to label / pc offset if not zero.
1093 void tbnz(const Register& rt, unsigned bit_pos, Label* label);
1094 void tbnz(const Register& rt, unsigned bit_pos, int imm14);
1096 // Address calculation instructions.
1097 // Calculate a PC-relative address. Unlike for branches the offset in adr is
1098 // unscaled (i.e. the result can be unaligned).
1099 void adr(const Register& rd, Label* label);
1100 void adr(const Register& rd, int imm21);
1102 // Data Processing instructions.
1104 void add(const Register& rd,
1106 const Operand& operand);
1108 // Add and update status flags.
1109 void adds(const Register& rd,
1111 const Operand& operand);
1113 // Compare negative.
1114 void cmn(const Register& rn, const Operand& operand);
1117 void sub(const Register& rd,
1119 const Operand& operand);
1121 // Subtract and update status flags.
1122 void subs(const Register& rd,
1124 const Operand& operand);
1127 void cmp(const Register& rn, const Operand& operand);
1130 void neg(const Register& rd,
1131 const Operand& operand);
1133 // Negate and update status flags.
1134 void negs(const Register& rd,
1135 const Operand& operand);
1137 // Add with carry bit.
1138 void adc(const Register& rd,
1140 const Operand& operand);
1142 // Add with carry bit and update status flags.
1143 void adcs(const Register& rd,
1145 const Operand& operand);
1147 // Subtract with carry bit.
1148 void sbc(const Register& rd,
1150 const Operand& operand);
1152 // Subtract with carry bit and update status flags.
1153 void sbcs(const Register& rd,
1155 const Operand& operand);
1157 // Negate with carry bit.
1158 void ngc(const Register& rd,
1159 const Operand& operand);
1161 // Negate with carry bit and update status flags.
1162 void ngcs(const Register& rd,
1163 const Operand& operand);
1165 // Logical instructions.
1166 // Bitwise and (A & B).
1167 void and_(const Register& rd,
1169 const Operand& operand);
1171 // Bitwise and (A & B) and update status flags.
1172 void ands(const Register& rd,
1174 const Operand& operand);
1176 // Bit test, and set flags.
1177 void tst(const Register& rn, const Operand& operand);
1179 // Bit clear (A & ~B).
1180 void bic(const Register& rd,
1182 const Operand& operand);
1184 // Bit clear (A & ~B) and update status flags.
1185 void bics(const Register& rd,
1187 const Operand& operand);
1189 // Bitwise or (A | B).
1190 void orr(const Register& rd, const Register& rn, const Operand& operand);
1192 // Bitwise nor (A | ~B).
1193 void orn(const Register& rd, const Register& rn, const Operand& operand);
1195 // Bitwise eor/xor (A ^ B).
1196 void eor(const Register& rd, const Register& rn, const Operand& operand);
1198 // Bitwise enor/xnor (A ^ ~B).
1199 void eon(const Register& rd, const Register& rn, const Operand& operand);
1201 // Logical shift left variable.
1202 void lslv(const Register& rd, const Register& rn, const Register& rm);
1204 // Logical shift right variable.
1205 void lsrv(const Register& rd, const Register& rn, const Register& rm);
1207 // Arithmetic shift right variable.
1208 void asrv(const Register& rd, const Register& rn, const Register& rm);
1210 // Rotate right variable.
1211 void rorv(const Register& rd, const Register& rn, const Register& rm);
1213 // Bitfield instructions.
1215 void bfm(const Register& rd,
1220 // Signed bitfield move.
1221 void sbfm(const Register& rd,
1226 // Unsigned bitfield move.
1227 void ubfm(const Register& rd,
1234 void bfi(const Register& rd,
1239 DCHECK(lsb + width <= rn.SizeInBits());
1240 bfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1);
1243 // Bitfield extract and insert low.
1244 void bfxil(const Register& rd,
1249 DCHECK(lsb + width <= rn.SizeInBits());
1250 bfm(rd, rn, lsb, lsb + width - 1);
1254 // Arithmetic shift right.
1255 void asr(const Register& rd, const Register& rn, unsigned shift) {
1256 DCHECK(shift < rd.SizeInBits());
1257 sbfm(rd, rn, shift, rd.SizeInBits() - 1);
1260 // Signed bitfield insert in zero.
1261 void sbfiz(const Register& rd,
1266 DCHECK(lsb + width <= rn.SizeInBits());
1267 sbfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1);
1270 // Signed bitfield extract.
1271 void sbfx(const Register& rd,
1276 DCHECK(lsb + width <= rn.SizeInBits());
1277 sbfm(rd, rn, lsb, lsb + width - 1);
1280 // Signed extend byte.
1281 void sxtb(const Register& rd, const Register& rn) {
1285 // Signed extend halfword.
1286 void sxth(const Register& rd, const Register& rn) {
1287 sbfm(rd, rn, 0, 15);
1290 // Signed extend word.
1291 void sxtw(const Register& rd, const Register& rn) {
1292 sbfm(rd, rn, 0, 31);
1296 // Logical shift left.
1297 void lsl(const Register& rd, const Register& rn, unsigned shift) {
1298 unsigned reg_size = rd.SizeInBits();
1299 DCHECK(shift < reg_size);
1300 ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1);
1303 // Logical shift right.
1304 void lsr(const Register& rd, const Register& rn, unsigned shift) {
1305 DCHECK(shift < rd.SizeInBits());
1306 ubfm(rd, rn, shift, rd.SizeInBits() - 1);
1309 // Unsigned bitfield insert in zero.
1310 void ubfiz(const Register& rd,
1315 DCHECK(lsb + width <= rn.SizeInBits());
1316 ubfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1);
1319 // Unsigned bitfield extract.
1320 void ubfx(const Register& rd,
1325 DCHECK(lsb + width <= rn.SizeInBits());
1326 ubfm(rd, rn, lsb, lsb + width - 1);
1329 // Unsigned extend byte.
1330 void uxtb(const Register& rd, const Register& rn) {
1334 // Unsigned extend halfword.
1335 void uxth(const Register& rd, const Register& rn) {
1336 ubfm(rd, rn, 0, 15);
1339 // Unsigned extend word.
1340 void uxtw(const Register& rd, const Register& rn) {
1341 ubfm(rd, rn, 0, 31);
1345 void extr(const Register& rd,
1350 // Conditional select: rd = cond ? rn : rm.
1351 void csel(const Register& rd,
1356 // Conditional select increment: rd = cond ? rn : rm + 1.
1357 void csinc(const Register& rd,
1362 // Conditional select inversion: rd = cond ? rn : ~rm.
1363 void csinv(const Register& rd,
1368 // Conditional select negation: rd = cond ? rn : -rm.
1369 void csneg(const Register& rd,
1374 // Conditional set: rd = cond ? 1 : 0.
1375 void cset(const Register& rd, Condition cond);
1377 // Conditional set minus: rd = cond ? -1 : 0.
1378 void csetm(const Register& rd, Condition cond);
1380 // Conditional increment: rd = cond ? rn + 1 : rn.
1381 void cinc(const Register& rd, const Register& rn, Condition cond);
1383 // Conditional invert: rd = cond ? ~rn : rn.
1384 void cinv(const Register& rd, const Register& rn, Condition cond);
1386 // Conditional negate: rd = cond ? -rn : rn.
1387 void cneg(const Register& rd, const Register& rn, Condition cond);
1390 void ror(const Register& rd, const Register& rs, unsigned shift) {
1391 extr(rd, rs, rs, shift);
1394 // Conditional comparison.
1395 // Conditional compare negative.
1396 void ccmn(const Register& rn,
1397 const Operand& operand,
1401 // Conditional compare.
1402 void ccmp(const Register& rn,
1403 const Operand& operand,
1408 // 32 x 32 -> 32-bit and 64 x 64 -> 64-bit multiply.
1409 void mul(const Register& rd, const Register& rn, const Register& rm);
1411 // 32 + 32 x 32 -> 32-bit and 64 + 64 x 64 -> 64-bit multiply accumulate.
1412 void madd(const Register& rd,
1415 const Register& ra);
1417 // -(32 x 32) -> 32-bit and -(64 x 64) -> 64-bit multiply.
1418 void mneg(const Register& rd, const Register& rn, const Register& rm);
1420 // 32 - 32 x 32 -> 32-bit and 64 - 64 x 64 -> 64-bit multiply subtract.
1421 void msub(const Register& rd,
1424 const Register& ra);
1426 // 32 x 32 -> 64-bit multiply.
1427 void smull(const Register& rd, const Register& rn, const Register& rm);
1429 // Xd = bits<127:64> of Xn * Xm.
1430 void smulh(const Register& rd, const Register& rn, const Register& rm);
1432 // Signed 32 x 32 -> 64-bit multiply and accumulate.
1433 void smaddl(const Register& rd,
1436 const Register& ra);
1438 // Unsigned 32 x 32 -> 64-bit multiply and accumulate.
1439 void umaddl(const Register& rd,
1442 const Register& ra);
1444 // Signed 32 x 32 -> 64-bit multiply and subtract.
1445 void smsubl(const Register& rd,
1448 const Register& ra);
1450 // Unsigned 32 x 32 -> 64-bit multiply and subtract.
1451 void umsubl(const Register& rd,
1454 const Register& ra);
1456 // Signed integer divide.
1457 void sdiv(const Register& rd, const Register& rn, const Register& rm);
1459 // Unsigned integer divide.
1460 void udiv(const Register& rd, const Register& rn, const Register& rm);
1462 // Bit count, bit reverse and endian reverse.
1463 void rbit(const Register& rd, const Register& rn);
1464 void rev16(const Register& rd, const Register& rn);
1465 void rev32(const Register& rd, const Register& rn);
1466 void rev(const Register& rd, const Register& rn);
1467 void clz(const Register& rd, const Register& rn);
1468 void cls(const Register& rd, const Register& rn);
1470 // Memory instructions.
1472 // Load integer or FP register.
1473 void ldr(const CPURegister& rt, const MemOperand& src);
1475 // Store integer or FP register.
1476 void str(const CPURegister& rt, const MemOperand& dst);
1478 // Load word with sign extension.
1479 void ldrsw(const Register& rt, const MemOperand& src);
1482 void ldrb(const Register& rt, const MemOperand& src);
1485 void strb(const Register& rt, const MemOperand& dst);
1487 // Load byte with sign extension.
1488 void ldrsb(const Register& rt, const MemOperand& src);
1491 void ldrh(const Register& rt, const MemOperand& src);
1494 void strh(const Register& rt, const MemOperand& dst);
1496 // Load half-word with sign extension.
1497 void ldrsh(const Register& rt, const MemOperand& src);
1499 // Load integer or FP register pair.
1500 void ldp(const CPURegister& rt, const CPURegister& rt2,
1501 const MemOperand& src);
1503 // Store integer or FP register pair.
1504 void stp(const CPURegister& rt, const CPURegister& rt2,
1505 const MemOperand& dst);
1507 // Load word pair with sign extension.
1508 void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src);
1510 // Load integer or FP register pair, non-temporal.
1511 void ldnp(const CPURegister& rt, const CPURegister& rt2,
1512 const MemOperand& src);
1514 // Store integer or FP register pair, non-temporal.
1515 void stnp(const CPURegister& rt, const CPURegister& rt2,
1516 const MemOperand& dst);
1518 // Load literal to register from a pc relative address.
1519 void ldr_pcrel(const CPURegister& rt, int imm19);
1521 // Load literal to register.
1522 void ldr(const CPURegister& rt, const Immediate& imm);
1524 // Move instructions. The default shift of -1 indicates that the move
1525 // instruction will calculate an appropriate 16-bit immediate and left shift
1526 // that is equal to the 64-bit immediate argument. If an explicit left shift
1527 // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value.
1529 // For movk, an explicit shift can be used to indicate which half word should
1530 // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant
1531 // half word with zero, whereas movk(x0, 0, 48) will overwrite the
1532 // most-significant.
1535 void movk(const Register& rd, uint64_t imm, int shift = -1) {
1536 MoveWide(rd, imm, shift, MOVK);
1539 // Move with non-zero.
1540 void movn(const Register& rd, uint64_t imm, int shift = -1) {
1541 MoveWide(rd, imm, shift, MOVN);
1545 void movz(const Register& rd, uint64_t imm, int shift = -1) {
1546 MoveWide(rd, imm, shift, MOVZ);
1549 // Misc instructions.
1550 // Monitor debug-mode breakpoint.
1553 // Halting debug-mode breakpoint.
1556 // Move register to register.
1557 void mov(const Register& rd, const Register& rn);
1559 // Move NOT(operand) to register.
1560 void mvn(const Register& rd, const Operand& operand);
1562 // System instructions.
1563 // Move to register from system register.
1564 void mrs(const Register& rt, SystemRegister sysreg);
1566 // Move from register to system register.
1567 void msr(SystemRegister sysreg, const Register& rt);
1570 void hint(SystemHint code);
1572 // Data memory barrier
1573 void dmb(BarrierDomain domain, BarrierType type);
1575 // Data synchronization barrier
1576 void dsb(BarrierDomain domain, BarrierType type);
1578 // Instruction synchronization barrier
1581 // Alias for system instructions.
1582 void nop() { hint(NOP); }
1584 // Different nop operations are used by the code generator to detect certain
1585 // states of the generated code.
1586 enum NopMarkerTypes {
1590 FIRST_NOP_MARKER = DEBUG_BREAK_NOP,
1591 LAST_NOP_MARKER = ADR_FAR_NOP
1594 void nop(NopMarkerTypes n) {
1595 DCHECK((FIRST_NOP_MARKER <= n) && (n <= LAST_NOP_MARKER));
1596 mov(Register::XRegFromCode(n), Register::XRegFromCode(n));
1600 // Move immediate to FP register.
1601 void fmov(FPRegister fd, double imm);
1602 void fmov(FPRegister fd, float imm);
1604 // Move FP register to register.
1605 void fmov(Register rd, FPRegister fn);
1607 // Move register to FP register.
1608 void fmov(FPRegister fd, Register rn);
1610 // Move FP register to FP register.
1611 void fmov(FPRegister fd, FPRegister fn);
1614 void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1617 void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1620 void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1622 // FP fused multiply and add.
1623 void fmadd(const FPRegister& fd,
1624 const FPRegister& fn,
1625 const FPRegister& fm,
1626 const FPRegister& fa);
1628 // FP fused multiply and subtract.
1629 void fmsub(const FPRegister& fd,
1630 const FPRegister& fn,
1631 const FPRegister& fm,
1632 const FPRegister& fa);
1634 // FP fused multiply, add and negate.
1635 void fnmadd(const FPRegister& fd,
1636 const FPRegister& fn,
1637 const FPRegister& fm,
1638 const FPRegister& fa);
1640 // FP fused multiply, subtract and negate.
1641 void fnmsub(const FPRegister& fd,
1642 const FPRegister& fn,
1643 const FPRegister& fm,
1644 const FPRegister& fa);
1647 void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1650 void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1653 void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1656 void fmaxnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1659 void fminnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1662 void fabs(const FPRegister& fd, const FPRegister& fn);
1665 void fneg(const FPRegister& fd, const FPRegister& fn);
1668 void fsqrt(const FPRegister& fd, const FPRegister& fn);
1670 // FP round to integer (nearest with ties to away).
1671 void frinta(const FPRegister& fd, const FPRegister& fn);
1673 // FP round to integer (toward minus infinity).
1674 void frintm(const FPRegister& fd, const FPRegister& fn);
1676 // FP round to integer (nearest with ties to even).
1677 void frintn(const FPRegister& fd, const FPRegister& fn);
1679 // FP round to integer (towards plus infinity).
1680 void frintp(const FPRegister& fd, const FPRegister& fn);
1682 // FP round to integer (towards zero.)
1683 void frintz(const FPRegister& fd, const FPRegister& fn);
1685 // FP compare registers.
1686 void fcmp(const FPRegister& fn, const FPRegister& fm);
1688 // FP compare immediate.
1689 void fcmp(const FPRegister& fn, double value);
1691 // FP conditional compare.
1692 void fccmp(const FPRegister& fn,
1693 const FPRegister& fm,
1697 // FP conditional select.
1698 void fcsel(const FPRegister& fd,
1699 const FPRegister& fn,
1700 const FPRegister& fm,
1703 // Common FP Convert function
1704 void FPConvertToInt(const Register& rd,
1705 const FPRegister& fn,
1706 FPIntegerConvertOp op);
1708 // FP convert between single and double precision.
1709 void fcvt(const FPRegister& fd, const FPRegister& fn);
1711 // Convert FP to unsigned integer (nearest with ties to away).
1712 void fcvtau(const Register& rd, const FPRegister& fn);
1714 // Convert FP to signed integer (nearest with ties to away).
1715 void fcvtas(const Register& rd, const FPRegister& fn);
1717 // Convert FP to unsigned integer (round towards -infinity).
1718 void fcvtmu(const Register& rd, const FPRegister& fn);
1720 // Convert FP to signed integer (round towards -infinity).
1721 void fcvtms(const Register& rd, const FPRegister& fn);
1723 // Convert FP to unsigned integer (nearest with ties to even).
1724 void fcvtnu(const Register& rd, const FPRegister& fn);
1726 // Convert FP to signed integer (nearest with ties to even).
1727 void fcvtns(const Register& rd, const FPRegister& fn);
1729 // Convert FP to unsigned integer (round towards zero).
1730 void fcvtzu(const Register& rd, const FPRegister& fn);
1732 // Convert FP to signed integer (rounf towards zero).
1733 void fcvtzs(const Register& rd, const FPRegister& fn);
1735 // Convert signed integer or fixed point to FP.
1736 void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
1738 // Convert unsigned integer or fixed point to FP.
1739 void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
1741 // Instruction functions used only for test, debug, and patching.
1742 // Emit raw instructions in the instruction stream.
1743 void dci(Instr raw_inst) { Emit(raw_inst); }
1745 // Emit 8 bits of data in the instruction stream.
1746 void dc8(uint8_t data) { EmitData(&data, sizeof(data)); }
1748 // Emit 32 bits of data in the instruction stream.
1749 void dc32(uint32_t data) { EmitData(&data, sizeof(data)); }
1751 // Emit 64 bits of data in the instruction stream.
1752 void dc64(uint64_t data) { EmitData(&data, sizeof(data)); }
1754 // Emit an address in the instruction stream.
1755 void dcptr(Label* label);
1757 // Copy a string into the instruction stream, including the terminating NULL
1758 // character. The instruction pointer (pc_) is then aligned correctly for
1759 // subsequent instructions.
1760 void EmitStringData(const char* string);
1762 // Pseudo-instructions ------------------------------------------------------
1764 // Parameters are described in arm64/instructions-arm64.h.
1765 void debug(const char* message, uint32_t code, Instr params = BREAK);
1768 void dd(uint32_t data) { dc32(data); }
1769 void db(uint8_t data) { dc8(data); }
1771 // Code generation helpers --------------------------------------------------
1773 bool IsConstPoolEmpty() const { return constpool_.IsEmpty(); }
1775 Instruction* pc() const { return Instruction::Cast(pc_); }
1777 Instruction* InstructionAt(int offset) const {
1778 return reinterpret_cast<Instruction*>(buffer_ + offset);
1781 ptrdiff_t InstructionOffset(Instruction* instr) const {
1782 return reinterpret_cast<byte*>(instr) - buffer_;
1785 // Register encoding.
1786 static Instr Rd(CPURegister rd) {
1787 DCHECK(rd.code() != kSPRegInternalCode);
1788 return rd.code() << Rd_offset;
1791 static Instr Rn(CPURegister rn) {
1792 DCHECK(rn.code() != kSPRegInternalCode);
1793 return rn.code() << Rn_offset;
1796 static Instr Rm(CPURegister rm) {
1797 DCHECK(rm.code() != kSPRegInternalCode);
1798 return rm.code() << Rm_offset;
1801 static Instr Ra(CPURegister ra) {
1802 DCHECK(ra.code() != kSPRegInternalCode);
1803 return ra.code() << Ra_offset;
1806 static Instr Rt(CPURegister rt) {
1807 DCHECK(rt.code() != kSPRegInternalCode);
1808 return rt.code() << Rt_offset;
1811 static Instr Rt2(CPURegister rt2) {
1812 DCHECK(rt2.code() != kSPRegInternalCode);
1813 return rt2.code() << Rt2_offset;
1816 // These encoding functions allow the stack pointer to be encoded, and
1817 // disallow the zero register.
1818 static Instr RdSP(Register rd) {
1819 DCHECK(!rd.IsZero());
1820 return (rd.code() & kRegCodeMask) << Rd_offset;
1823 static Instr RnSP(Register rn) {
1824 DCHECK(!rn.IsZero());
1825 return (rn.code() & kRegCodeMask) << Rn_offset;
1829 inline static Instr Flags(FlagsUpdate S);
1830 inline static Instr Cond(Condition cond);
1832 // PC-relative address encoding.
1833 inline static Instr ImmPCRelAddress(int imm21);
1836 inline static Instr ImmUncondBranch(int imm26);
1837 inline static Instr ImmCondBranch(int imm19);
1838 inline static Instr ImmCmpBranch(int imm19);
1839 inline static Instr ImmTestBranch(int imm14);
1840 inline static Instr ImmTestBranchBit(unsigned bit_pos);
1842 // Data Processing encoding.
1843 inline static Instr SF(Register rd);
1844 inline static Instr ImmAddSub(int64_t imm);
1845 inline static Instr ImmS(unsigned imms, unsigned reg_size);
1846 inline static Instr ImmR(unsigned immr, unsigned reg_size);
1847 inline static Instr ImmSetBits(unsigned imms, unsigned reg_size);
1848 inline static Instr ImmRotate(unsigned immr, unsigned reg_size);
1849 inline static Instr ImmLLiteral(int imm19);
1850 inline static Instr BitN(unsigned bitn, unsigned reg_size);
1851 inline static Instr ShiftDP(Shift shift);
1852 inline static Instr ImmDPShift(unsigned amount);
1853 inline static Instr ExtendMode(Extend extend);
1854 inline static Instr ImmExtendShift(unsigned left_shift);
1855 inline static Instr ImmCondCmp(unsigned imm);
1856 inline static Instr Nzcv(StatusFlags nzcv);
1858 static bool IsImmAddSub(int64_t immediate);
1859 static bool IsImmLogical(uint64_t value,
1865 // MemOperand offset encoding.
1866 inline static Instr ImmLSUnsigned(int imm12);
1867 inline static Instr ImmLS(int imm9);
1868 inline static Instr ImmLSPair(int imm7, LSDataSize size);
1869 inline static Instr ImmShiftLS(unsigned shift_amount);
1870 inline static Instr ImmException(int imm16);
1871 inline static Instr ImmSystemRegister(int imm15);
1872 inline static Instr ImmHint(int imm7);
1873 inline static Instr ImmBarrierDomain(int imm2);
1874 inline static Instr ImmBarrierType(int imm2);
1875 inline static LSDataSize CalcLSDataSize(LoadStoreOp op);
1877 static bool IsImmLSUnscaled(int64_t offset);
1878 static bool IsImmLSScaled(int64_t offset, LSDataSize size);
1880 // Move immediates encoding.
1881 inline static Instr ImmMoveWide(uint64_t imm);
1882 inline static Instr ShiftMoveWide(int64_t shift);
1885 static Instr ImmFP32(float imm);
1886 static Instr ImmFP64(double imm);
1887 inline static Instr FPScale(unsigned scale);
1889 // FP register type.
1890 inline static Instr FPType(FPRegister fd);
1892 // Class for scoping postponing the constant pool generation.
1893 class BlockConstPoolScope {
1895 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1896 assem_->StartBlockConstPool();
1898 ~BlockConstPoolScope() {
1899 assem_->EndBlockConstPool();
1905 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1908 // Check if is time to emit a constant pool.
1909 void CheckConstPool(bool force_emit, bool require_jump);
1911 // Allocate a constant pool of the correct size for the generated code.
1912 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
1914 // Generate the constant pool for the generated code.
1915 void PopulateConstantPool(ConstantPoolArray* constant_pool);
1917 // Returns true if we should emit a veneer as soon as possible for a branch
1918 // which can at most reach to specified pc.
1919 bool ShouldEmitVeneer(int max_reachable_pc,
1920 int margin = kVeneerDistanceMargin);
1921 bool ShouldEmitVeneers(int margin = kVeneerDistanceMargin) {
1922 return ShouldEmitVeneer(unresolved_branches_first_limit(), margin);
1925 // The maximum code size generated for a veneer. Currently one branch
1926 // instruction. This is for code size checking purposes, and can be extended
1927 // in the future for example if we decide to add nops between the veneers.
1928 static const int kMaxVeneerCodeSize = 1 * kInstructionSize;
1930 void RecordVeneerPool(int location_offset, int size);
1931 // Emits veneers for branches that are approaching their maximum range.
1932 // If need_protection is true, the veneers are protected by a branch jumping
1934 void EmitVeneers(bool force_emit, bool need_protection,
1935 int margin = kVeneerDistanceMargin);
1936 void EmitVeneersGuard() { EmitPoolGuard(); }
1937 // Checks whether veneers need to be emitted at this point.
1938 // If force_emit is set, a veneer is generated for *all* unresolved branches.
1939 void CheckVeneerPool(bool force_emit, bool require_jump,
1940 int margin = kVeneerDistanceMargin);
1942 class BlockPoolsScope {
1944 explicit BlockPoolsScope(Assembler* assem) : assem_(assem) {
1945 assem_->StartBlockPools();
1947 ~BlockPoolsScope() {
1948 assem_->EndBlockPools();
1954 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope);
1958 inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const;
1960 void LoadStore(const CPURegister& rt,
1961 const MemOperand& addr,
1964 void LoadStorePair(const CPURegister& rt, const CPURegister& rt2,
1965 const MemOperand& addr, LoadStorePairOp op);
1966 static bool IsImmLSPair(int64_t offset, LSDataSize size);
1968 void Logical(const Register& rd,
1970 const Operand& operand,
1972 void LogicalImmediate(const Register& rd,
1979 void ConditionalCompare(const Register& rn,
1980 const Operand& operand,
1983 ConditionalCompareOp op);
1984 static bool IsImmConditionalCompare(int64_t immediate);
1986 void AddSubWithCarry(const Register& rd,
1988 const Operand& operand,
1990 AddSubWithCarryOp op);
1992 // Functions for emulating operands not directly supported by the instruction
1994 void EmitShift(const Register& rd,
1998 void EmitExtendShift(const Register& rd,
2001 unsigned left_shift);
2003 void AddSub(const Register& rd,
2005 const Operand& operand,
2009 static bool IsImmFP32(float imm);
2010 static bool IsImmFP64(double imm);
2012 // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified
2013 // registers. Only simple loads are supported; sign- and zero-extension (such
2014 // as in LDPSW_x or LDRB_w) are not supported.
2015 static inline LoadStoreOp LoadOpFor(const CPURegister& rt);
2016 static inline LoadStorePairOp LoadPairOpFor(const CPURegister& rt,
2017 const CPURegister& rt2);
2018 static inline LoadStoreOp StoreOpFor(const CPURegister& rt);
2019 static inline LoadStorePairOp StorePairOpFor(const CPURegister& rt,
2020 const CPURegister& rt2);
2021 static inline LoadStorePairNonTemporalOp LoadPairNonTemporalOpFor(
2022 const CPURegister& rt, const CPURegister& rt2);
2023 static inline LoadStorePairNonTemporalOp StorePairNonTemporalOpFor(
2024 const CPURegister& rt, const CPURegister& rt2);
2025 static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt);
2027 // Remove the specified branch from the unbound label link chain.
2028 // If available, a veneer for this label can be used for other branches in the
2029 // chain if the link chain cannot be fixed up without this branch.
2030 void RemoveBranchFromLabelLinkChain(Instruction* branch,
2032 Instruction* label_veneer = NULL);
2035 // Instruction helpers.
2036 void MoveWide(const Register& rd,
2039 MoveWideImmediateOp mov_op);
2040 void DataProcShiftedRegister(const Register& rd,
2042 const Operand& operand,
2045 void DataProcExtendedRegister(const Register& rd,
2047 const Operand& operand,
2050 void LoadStorePairNonTemporal(const CPURegister& rt,
2051 const CPURegister& rt2,
2052 const MemOperand& addr,
2053 LoadStorePairNonTemporalOp op);
2054 void ConditionalSelect(const Register& rd,
2058 ConditionalSelectOp op);
2059 void DataProcessing1Source(const Register& rd,
2061 DataProcessing1SourceOp op);
2062 void DataProcessing3Source(const Register& rd,
2066 DataProcessing3SourceOp op);
2067 void FPDataProcessing1Source(const FPRegister& fd,
2068 const FPRegister& fn,
2069 FPDataProcessing1SourceOp op);
2070 void FPDataProcessing2Source(const FPRegister& fd,
2071 const FPRegister& fn,
2072 const FPRegister& fm,
2073 FPDataProcessing2SourceOp op);
2074 void FPDataProcessing3Source(const FPRegister& fd,
2075 const FPRegister& fn,
2076 const FPRegister& fm,
2077 const FPRegister& fa,
2078 FPDataProcessing3SourceOp op);
2082 // Return an offset for a label-referencing instruction, typically a branch.
2083 int LinkAndGetByteOffsetTo(Label* label);
2085 // This is the same as LinkAndGetByteOffsetTo, but return an offset
2086 // suitable for fields that take instruction offsets.
2087 inline int LinkAndGetInstructionOffsetTo(Label* label);
2089 static const int kStartOfLabelLinkChain = 0;
2091 // Verify that a label's link chain is intact.
2092 void CheckLabelLinkChain(Label const * label);
2094 void RecordLiteral(int64_t imm, unsigned size);
2096 // Postpone the generation of the constant pool for the specified number of
2098 void BlockConstPoolFor(int instructions);
2100 // Set how far from current pc the next constant pool check will be.
2101 void SetNextConstPoolCheckIn(int instructions) {
2102 next_constant_pool_check_ = pc_offset() + instructions * kInstructionSize;
2105 // Emit the instruction at pc_.
2106 void Emit(Instr instruction) {
2107 STATIC_ASSERT(sizeof(*pc_) == 1);
2108 STATIC_ASSERT(sizeof(instruction) == kInstructionSize);
2109 DCHECK((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_));
2111 memcpy(pc_, &instruction, sizeof(instruction));
2112 pc_ += sizeof(instruction);
2116 // Emit data inline in the instruction stream.
2117 void EmitData(void const * data, unsigned size) {
2118 DCHECK(sizeof(*pc_) == 1);
2119 DCHECK((pc_ + size) <= (buffer_ + buffer_size_));
2121 // TODO(all): Somehow register we have some data here. Then we can
2122 // disassemble it correctly.
2123 memcpy(pc_, data, size);
2129 void CheckBufferSpace();
2132 // Pc offset of the next constant pool check.
2133 int next_constant_pool_check_;
2135 // Constant pool generation
2136 // Pools are emitted in the instruction stream. They are emitted when:
2137 // * the distance to the first use is above a pre-defined distance or
2138 // * the numbers of entries in the pool is above a pre-defined size or
2139 // * code generation is finished
2140 // If a pool needs to be emitted before code generation is finished a branch
2141 // over the emitted pool will be inserted.
2143 // Constants in the pool may be addresses of functions that gets relocated;
2144 // if so, a relocation info entry is associated to the constant pool entry.
2146 // Repeated checking whether the constant pool should be emitted is rather
2147 // expensive. By default we only check again once a number of instructions
2148 // has been generated. That also means that the sizing of the buffers is not
2149 // an exact science, and that we rely on some slop to not overrun buffers.
2150 static const int kCheckConstPoolInterval = 128;
2152 // Distance to first use after a which a pool will be emitted. Pool entries
2153 // are accessed with pc relative load therefore this cannot be more than
2154 // 1 * MB. Since constant pool emission checks are interval based this value
2155 // is an approximation.
2156 static const int kApproxMaxDistToConstPool = 64 * KB;
2158 // Number of pool entries after which a pool will be emitted. Since constant
2159 // pool emission checks are interval based this value is an approximation.
2160 static const int kApproxMaxPoolEntryCount = 512;
2162 // Emission of the constant pool may be blocked in some code sequences.
2163 int const_pool_blocked_nesting_; // Block emission if this is not zero.
2164 int no_const_pool_before_; // Block emission before this pc offset.
2166 // Emission of the veneer pools may be blocked in some code sequences.
2167 int veneer_pool_blocked_nesting_; // Block emission if this is not zero.
2169 // Relocation info generation
2170 // Each relocation is encoded as a variable size value
2171 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
2172 RelocInfoWriter reloc_info_writer;
2173 // Internal reference positions, required for (potential) patching in
2174 // GrowBuffer(); contains only those internal references whose labels
2175 // are already bound.
2176 std::deque<int> internal_reference_positions_;
2178 // Relocation info records are also used during code generation as temporary
2179 // containers for constants and code target addresses until they are emitted
2180 // to the constant pool. These pending relocation info records are temporarily
2181 // stored in a separate buffer until a constant pool is emitted.
2182 // If every instruction in a long sequence is accessing the pool, we need one
2183 // pending relocation entry per instruction.
2185 // The pending constant pool.
2186 ConstPool constpool_;
2188 // Relocation for a type-recording IC has the AST id added to it. This
2189 // member variable is a way to pass the information from the call site to
2190 // the relocation info.
2191 TypeFeedbackId recorded_ast_id_;
2193 inline TypeFeedbackId RecordedAstId();
2194 inline void ClearRecordedAstId();
2197 // Record the AST id of the CallIC being compiled, so that it can be placed
2198 // in the relocation information.
2199 void SetRecordedAstId(TypeFeedbackId ast_id) {
2200 DCHECK(recorded_ast_id_.IsNone());
2201 recorded_ast_id_ = ast_id;
2205 // The relocation writer's position is at least kGap bytes below the end of
2206 // the generated instructions. This is so that multi-instruction sequences do
2207 // not have to check for overflow. The same is true for writes of large
2208 // relocation info entries, and debug strings encoded in the instruction
2210 static const int kGap = 128;
2213 class FarBranchInfo {
2215 FarBranchInfo(int offset, Label* label)
2216 : pc_offset_(offset), label_(label) {}
2217 // Offset of the branch in the code generation buffer.
2219 // The label branched to.
2224 // Information about unresolved (forward) branches.
2225 // The Assembler is only allowed to delete out-of-date information from here
2226 // after a label is bound. The MacroAssembler uses this information to
2227 // generate veneers.
2229 // The second member gives information about the unresolved branch. The first
2230 // member of the pair is the maximum offset that the branch can reach in the
2231 // buffer. The map is sorted according to this reachable offset, allowing to
2232 // easily check when veneers need to be emitted.
2233 // Note that the maximum reachable offset (first member of the pairs) should
2234 // always be positive but has the same type as the return value for
2235 // pc_offset() for convenience.
2236 std::multimap<int, FarBranchInfo> unresolved_branches_;
2238 // We generate a veneer for a branch if we reach within this distance of the
2239 // limit of the range.
2240 static const int kVeneerDistanceMargin = 1 * KB;
2241 // The factor of 2 is a finger in the air guess. With a default margin of
2242 // 1KB, that leaves us an addional 256 instructions to avoid generating a
2243 // protective branch.
2244 static const int kVeneerNoProtectionFactor = 2;
2245 static const int kVeneerDistanceCheckMargin =
2246 kVeneerNoProtectionFactor * kVeneerDistanceMargin;
2247 int unresolved_branches_first_limit() const {
2248 DCHECK(!unresolved_branches_.empty());
2249 return unresolved_branches_.begin()->first;
2251 // This is similar to next_constant_pool_check_ and helps reduce the overhead
2252 // of checking for veneer pools.
2253 // It is maintained to the closest unresolved branch limit minus the maximum
2254 // veneer margin (or kMaxInt if there are no unresolved branches).
2255 int next_veneer_pool_check_;
2258 // If a veneer is emitted for a branch instruction, that instruction must be
2259 // removed from the associated label's link chain so that the assembler does
2260 // not later attempt (likely unsuccessfully) to patch it to branch directly to
2262 void DeleteUnresolvedBranchInfoForLabel(Label* label);
2263 // This function deletes the information related to the label by traversing
2264 // the label chain, and for each PC-relative instruction in the chain checking
2265 // if pending unresolved information exists. Its complexity is proportional to
2266 // the length of the label chain.
2267 void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label);
2270 PositionsRecorder positions_recorder_;
2271 friend class PositionsRecorder;
2272 friend class EnsureSpace;
2273 friend class ConstPool;
2276 class PatchingAssembler : public Assembler {
2278 // Create an Assembler with a buffer starting at 'start'.
2279 // The buffer size is
2280 // size of instructions to patch + kGap
2281 // Where kGap is the distance from which the Assembler tries to grow the
2283 // If more or fewer instructions than expected are generated or if some
2284 // relocation information takes space in the buffer, the PatchingAssembler
2285 // will crash trying to grow the buffer.
2286 PatchingAssembler(Instruction* start, unsigned count)
2288 reinterpret_cast<byte*>(start),
2289 count * kInstructionSize + kGap) {
2293 PatchingAssembler(byte* start, unsigned count)
2294 : Assembler(NULL, start, count * kInstructionSize + kGap) {
2295 // Block constant pool emission.
2299 ~PatchingAssembler() {
2300 // Const pool should still be blocked.
2301 DCHECK(is_const_pool_blocked());
2303 // Verify we have generated the number of instruction we expected.
2304 DCHECK((pc_offset() + kGap) == buffer_size_);
2305 // Verify no relocation information has been emitted.
2306 DCHECK(IsConstPoolEmpty());
2307 // Flush the Instruction cache.
2308 size_t length = buffer_size_ - kGap;
2309 CpuFeatures::FlushICache(buffer_, length);
2312 // See definition of PatchAdrFar() for details.
2313 static const int kAdrFarPatchableNNops = 2;
2314 static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 2;
2315 void PatchAdrFar(int64_t target_offset);
2319 class EnsureSpace BASE_EMBEDDED {
2321 explicit EnsureSpace(Assembler* assembler) {
2322 assembler->CheckBufferSpace();
2326 } } // namespace v8::internal
2328 #endif // V8_ARM64_ASSEMBLER_ARM64_H_