1 // Copyright 2013 the V8 project authors. All rights reserved.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following
11 // disclaimer in the documentation and/or other materials provided
12 // with the distribution.
13 // * Neither the name of Google Inc. nor the names of its
14 // contributors may be used to endorse or promote products derived
15 // from this software without specific prior written permission.
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #if V8_TARGET_ARCH_ARM64
33 #define ARM64_DEFINE_REG_STATICS
35 #include "src/arm64/assembler-arm64-inl.h"
36 #include "src/base/bits.h"
37 #include "src/base/cpu.h"
43 // -----------------------------------------------------------------------------
44 // CpuFeatures implementation.
46 void CpuFeatures::ProbeImpl(bool cross_compile) {
47 // AArch64 has no configuration options, no further probing is required.
50 // Only use statically determined features for cross compile (snapshot).
51 if (cross_compile) return;
53 // Probe for runtime features
55 if (cpu.implementer() == base::CPU::NVIDIA &&
56 cpu.variant() == base::CPU::NVIDIA_DENVER) {
57 supported_ |= 1u << COHERENT_CACHE;
62 void CpuFeatures::PrintTarget() { }
65 void CpuFeatures::PrintFeatures() {
66 printf("COHERENT_CACHE=%d\n", CpuFeatures::IsSupported(COHERENT_CACHE));
70 // -----------------------------------------------------------------------------
71 // CPURegList utilities.
73 CPURegister CPURegList::PopLowestIndex() {
78 int index = CountTrailingZeros(list_, kRegListSizeInBits);
79 DCHECK((1 << index) & list_);
81 return CPURegister::Create(index, size_, type_);
85 CPURegister CPURegList::PopHighestIndex() {
90 int index = CountLeadingZeros(list_, kRegListSizeInBits);
91 index = kRegListSizeInBits - 1 - index;
92 DCHECK((1 << index) & list_);
94 return CPURegister::Create(index, size_, type_);
98 void CPURegList::RemoveCalleeSaved() {
99 if (type() == CPURegister::kRegister) {
100 Remove(GetCalleeSaved(RegisterSizeInBits()));
101 } else if (type() == CPURegister::kFPRegister) {
102 Remove(GetCalleeSavedFP(RegisterSizeInBits()));
104 DCHECK(type() == CPURegister::kNoRegister);
106 // The list must already be empty, so do nothing.
111 CPURegList CPURegList::GetCalleeSaved(unsigned size) {
112 return CPURegList(CPURegister::kRegister, size, 19, 29);
116 CPURegList CPURegList::GetCalleeSavedFP(unsigned size) {
117 return CPURegList(CPURegister::kFPRegister, size, 8, 15);
121 CPURegList CPURegList::GetCallerSaved(unsigned size) {
122 // Registers x0-x18 and lr (x30) are caller-saved.
123 CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18);
129 CPURegList CPURegList::GetCallerSavedFP(unsigned size) {
130 // Registers d0-d7 and d16-d31 are caller-saved.
131 CPURegList list = CPURegList(CPURegister::kFPRegister, size, 0, 7);
132 list.Combine(CPURegList(CPURegister::kFPRegister, size, 16, 31));
137 // This function defines the list of registers which are associated with a
138 // safepoint slot. Safepoint register slots are saved contiguously on the stack.
139 // MacroAssembler::SafepointRegisterStackIndex handles mapping from register
140 // code to index in the safepoint register slots. Any change here can affect
142 CPURegList CPURegList::GetSafepointSavedRegisters() {
143 CPURegList list = CPURegList::GetCalleeSaved();
145 CPURegList(CPURegister::kRegister, kXRegSizeInBits, kJSCallerSaved));
147 // Note that unfortunately we can't use symbolic names for registers and have
148 // to directly use register codes. This is because this function is used to
149 // initialize some static variables and we can't rely on register variables
150 // to be initialized due to static initialization order issues in C++.
152 // Drop ip0 and ip1 (i.e. x16 and x17), as they should not be expected to be
153 // preserved outside of the macro assembler.
157 // Add x18 to the safepoint list, as although it's not in kJSCallerSaved, it
158 // is a caller-saved register according to the procedure call standard.
161 // Drop jssp as the stack pointer doesn't need to be included.
164 // Add the link register (x30) to the safepoint list.
171 // -----------------------------------------------------------------------------
172 // Implementation of RelocInfo
174 const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE;
177 bool RelocInfo::IsCodedSpecially() {
178 // The deserializer needs to know whether a pointer is specially coded. Being
179 // specially coded on ARM64 means that it is a movz/movk sequence. We don't
180 // generate those for relocatable pointers.
185 bool RelocInfo::IsInConstantPool() {
186 Instruction* instr = reinterpret_cast<Instruction*>(pc_);
187 return instr->IsLdrLiteralX();
191 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2,
192 Register reg3, Register reg4) {
193 CPURegList regs(reg1, reg2, reg3, reg4);
194 for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
195 Register candidate = Register::FromAllocationIndex(i);
196 if (regs.IncludesAliasOf(candidate)) continue;
204 bool AreAliased(const CPURegister& reg1, const CPURegister& reg2,
205 const CPURegister& reg3, const CPURegister& reg4,
206 const CPURegister& reg5, const CPURegister& reg6,
207 const CPURegister& reg7, const CPURegister& reg8) {
208 int number_of_valid_regs = 0;
209 int number_of_valid_fpregs = 0;
211 RegList unique_regs = 0;
212 RegList unique_fpregs = 0;
214 const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};
216 for (unsigned i = 0; i < arraysize(regs); i++) {
217 if (regs[i].IsRegister()) {
218 number_of_valid_regs++;
219 unique_regs |= regs[i].Bit();
220 } else if (regs[i].IsFPRegister()) {
221 number_of_valid_fpregs++;
222 unique_fpregs |= regs[i].Bit();
224 DCHECK(!regs[i].IsValid());
228 int number_of_unique_regs =
229 CountSetBits(unique_regs, sizeof(unique_regs) * kBitsPerByte);
230 int number_of_unique_fpregs =
231 CountSetBits(unique_fpregs, sizeof(unique_fpregs) * kBitsPerByte);
233 DCHECK(number_of_valid_regs >= number_of_unique_regs);
234 DCHECK(number_of_valid_fpregs >= number_of_unique_fpregs);
236 return (number_of_valid_regs != number_of_unique_regs) ||
237 (number_of_valid_fpregs != number_of_unique_fpregs);
241 bool AreSameSizeAndType(const CPURegister& reg1, const CPURegister& reg2,
242 const CPURegister& reg3, const CPURegister& reg4,
243 const CPURegister& reg5, const CPURegister& reg6,
244 const CPURegister& reg7, const CPURegister& reg8) {
245 DCHECK(reg1.IsValid());
247 match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1);
248 match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1);
249 match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1);
250 match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1);
251 match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1);
252 match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1);
253 match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1);
258 void Immediate::InitializeHandle(Handle<Object> handle) {
259 AllowDeferredHandleDereference using_raw_address;
261 // Verify all Objects referred by code are NOT in new space.
262 Object* obj = *handle;
263 if (obj->IsHeapObject()) {
264 DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
265 value_ = reinterpret_cast<intptr_t>(handle.location());
266 rmode_ = RelocInfo::EMBEDDED_OBJECT;
268 STATIC_ASSERT(sizeof(intptr_t) == sizeof(int64_t));
269 value_ = reinterpret_cast<intptr_t>(obj);
270 rmode_ = RelocInfo::NONE64;
275 bool Operand::NeedsRelocation(const Assembler* assembler) const {
276 RelocInfo::Mode rmode = immediate_.rmode();
278 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
279 return assembler->serializer_enabled();
282 return !RelocInfo::IsNone(rmode);
287 void ConstPool::RecordEntry(intptr_t data,
288 RelocInfo::Mode mode) {
289 DCHECK(mode != RelocInfo::COMMENT &&
290 mode != RelocInfo::POSITION &&
291 mode != RelocInfo::STATEMENT_POSITION &&
292 mode != RelocInfo::CONST_POOL &&
293 mode != RelocInfo::VENEER_POOL &&
294 mode != RelocInfo::CODE_AGE_SEQUENCE &&
295 mode != RelocInfo::DEOPT_REASON);
296 uint64_t raw_data = static_cast<uint64_t>(data);
297 int offset = assm_->pc_offset();
302 std::pair<uint64_t, int> entry = std::make_pair(raw_data, offset);
303 if (CanBeShared(mode)) {
304 shared_entries_.insert(entry);
305 if (shared_entries_.count(entry.first) == 1) {
306 shared_entries_count++;
309 unique_entries_.push_back(entry);
312 if (EntryCount() > Assembler::kApproxMaxPoolEntryCount) {
313 // Request constant pool emission after the next instruction.
314 assm_->SetNextConstPoolCheckIn(1);
319 int ConstPool::DistanceToFirstUse() {
320 DCHECK(first_use_ >= 0);
321 return assm_->pc_offset() - first_use_;
325 int ConstPool::MaxPcOffset() {
326 // There are no pending entries in the pool so we can never get out of
328 if (IsEmpty()) return kMaxInt;
330 // Entries are not necessarily emitted in the order they are added so in the
331 // worst case the first constant pool use will be accessing the last entry.
332 return first_use_ + kMaxLoadLiteralRange - WorstCaseSize();
336 int ConstPool::WorstCaseSize() {
337 if (IsEmpty()) return 0;
339 // Max size prologue:
341 // ldr xzr, #pool_size
344 // All entries are 64-bit for now.
345 return 4 * kInstructionSize + EntryCount() * kPointerSize;
349 int ConstPool::SizeIfEmittedAtCurrentPc(bool require_jump) {
350 if (IsEmpty()) return 0;
353 // b over ;; if require_jump
354 // ldr xzr, #pool_size
356 // nop ;; if not 64-bit aligned
357 int prologue_size = require_jump ? kInstructionSize : 0;
358 prologue_size += 2 * kInstructionSize;
359 prologue_size += IsAligned(assm_->pc_offset() + prologue_size, 8) ?
360 0 : kInstructionSize;
362 // All entries are 64-bit for now.
363 return prologue_size + EntryCount() * kPointerSize;
367 void ConstPool::Emit(bool require_jump) {
368 DCHECK(!assm_->is_const_pool_blocked());
369 // Prevent recursive pool emission and protect from veneer pools.
370 Assembler::BlockPoolsScope block_pools(assm_);
372 int size = SizeIfEmittedAtCurrentPc(require_jump);
374 assm_->bind(&size_check);
376 assm_->RecordConstPool(size);
377 // Emit the constant pool. It is preceded by an optional branch if
378 // require_jump and a header which will:
379 // 1) Encode the size of the constant pool, for use by the disassembler.
380 // 2) Terminate the program, to try to prevent execution from accidentally
381 // flowing into the constant pool.
382 // 3) align the pool entries to 64-bit.
383 // The header is therefore made of up to three arm64 instructions:
384 // ldr xzr, #<size of the constant pool in 32-bit words>
388 // If executed, the header will likely segfault and lr will point to the
389 // instruction following the offending blr.
390 // TODO(all): Make the alignment part less fragile. Currently code is
391 // allocated as a byte array so there are no guarantees the alignment will
392 // be preserved on compaction. Currently it works as allocation seems to be
395 // Emit branch if required
398 assm_->b(&after_pool);
402 assm_->RecordComment("[ Constant Pool");
407 // Emit constant pool entries.
408 // TODO(all): currently each relocated constant is 64 bits, consider adding
409 // support for 32-bit entries.
411 assm_->RecordComment("]");
413 if (after_pool.is_linked()) {
414 assm_->bind(&after_pool);
417 DCHECK(assm_->SizeOfCodeGeneratedSince(&size_check) ==
418 static_cast<unsigned>(size));
422 void ConstPool::Clear() {
423 shared_entries_.clear();
424 shared_entries_count = 0;
425 unique_entries_.clear();
430 bool ConstPool::CanBeShared(RelocInfo::Mode mode) {
431 // Constant pool currently does not support 32-bit entries.
432 DCHECK(mode != RelocInfo::NONE32);
434 return RelocInfo::IsNone(mode) ||
435 (!assm_->serializer_enabled() && (mode >= RelocInfo::CELL));
439 void ConstPool::EmitMarker() {
440 // A constant pool size is expressed in number of 32-bits words.
441 // Currently all entries are 64-bit.
442 // + 1 is for the crash guard.
443 // + 0/1 for alignment.
444 int word_count = EntryCount() * 2 + 1 +
445 (IsAligned(assm_->pc_offset(), 8) ? 0 : 1);
446 assm_->Emit(LDR_x_lit |
447 Assembler::ImmLLiteral(word_count) |
452 MemOperand::PairResult MemOperand::AreConsistentForPair(
453 const MemOperand& operandA,
454 const MemOperand& operandB,
455 int access_size_log2) {
456 DCHECK(access_size_log2 >= 0);
457 DCHECK(access_size_log2 <= 3);
458 // Step one: check that they share the same base, that the mode is Offset
459 // and that the offset is a multiple of access size.
460 if (!operandA.base().Is(operandB.base()) ||
461 (operandA.addrmode() != Offset) ||
462 (operandB.addrmode() != Offset) ||
463 ((operandA.offset() & ((1 << access_size_log2) - 1)) != 0)) {
466 // Step two: check that the offsets are contiguous and that the range
467 // is OK for ldp/stp.
468 if ((operandB.offset() == operandA.offset() + (1 << access_size_log2)) &&
469 is_int7(operandA.offset() >> access_size_log2)) {
472 if ((operandA.offset() == operandB.offset() + (1 << access_size_log2)) &&
473 is_int7(operandB.offset() >> access_size_log2)) {
480 void ConstPool::EmitGuard() {
482 Instruction* instr = reinterpret_cast<Instruction*>(assm_->pc());
483 DCHECK(instr->preceding()->IsLdrLiteralX() &&
484 instr->preceding()->Rt() == xzr.code());
486 assm_->EmitPoolGuard();
490 void ConstPool::EmitEntries() {
491 DCHECK(IsAligned(assm_->pc_offset(), 8));
493 typedef std::multimap<uint64_t, int>::const_iterator SharedEntriesIterator;
494 SharedEntriesIterator value_it;
495 // Iterate through the keys (constant pool values).
496 for (value_it = shared_entries_.begin();
497 value_it != shared_entries_.end();
498 value_it = shared_entries_.upper_bound(value_it->first)) {
499 std::pair<SharedEntriesIterator, SharedEntriesIterator> range;
500 uint64_t data = value_it->first;
501 range = shared_entries_.equal_range(data);
502 SharedEntriesIterator offset_it;
503 // Iterate through the offsets of a given key.
504 for (offset_it = range.first; offset_it != range.second; offset_it++) {
505 Instruction* instr = assm_->InstructionAt(offset_it->second);
507 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0.
508 DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0);
509 instr->SetImmPCOffsetTarget(assm_->pc());
513 shared_entries_.clear();
514 shared_entries_count = 0;
516 // Emit unique entries.
517 std::vector<std::pair<uint64_t, int> >::const_iterator unique_it;
518 for (unique_it = unique_entries_.begin();
519 unique_it != unique_entries_.end();
521 Instruction* instr = assm_->InstructionAt(unique_it->second);
523 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0.
524 DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0);
525 instr->SetImmPCOffsetTarget(assm_->pc());
526 assm_->dc64(unique_it->first);
528 unique_entries_.clear();
534 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
535 : AssemblerBase(isolate, buffer, buffer_size),
537 recorded_ast_id_(TypeFeedbackId::None()),
538 unresolved_branches_(),
539 positions_recorder_(this) {
540 const_pool_blocked_nesting_ = 0;
541 veneer_pool_blocked_nesting_ = 0;
546 Assembler::~Assembler() {
547 DCHECK(constpool_.IsEmpty());
548 DCHECK(const_pool_blocked_nesting_ == 0);
549 DCHECK(veneer_pool_blocked_nesting_ == 0);
553 void Assembler::Reset() {
555 DCHECK((pc_ >= buffer_) && (pc_ < buffer_ + buffer_size_));
556 DCHECK(const_pool_blocked_nesting_ == 0);
557 DCHECK(veneer_pool_blocked_nesting_ == 0);
558 DCHECK(unresolved_branches_.empty());
559 memset(buffer_, 0, pc_ - buffer_);
562 reloc_info_writer.Reposition(reinterpret_cast<byte*>(buffer_ + buffer_size_),
563 reinterpret_cast<byte*>(pc_));
565 next_constant_pool_check_ = 0;
566 next_veneer_pool_check_ = kMaxInt;
567 no_const_pool_before_ = 0;
568 ClearRecordedAstId();
572 void Assembler::GetCode(CodeDesc* desc) {
573 reloc_info_writer.Finish();
574 // Emit constant pool if necessary.
575 CheckConstPool(true, false);
576 DCHECK(constpool_.IsEmpty());
578 // Set up code descriptor.
580 desc->buffer = reinterpret_cast<byte*>(buffer_);
581 desc->buffer_size = buffer_size_;
582 desc->instr_size = pc_offset();
583 desc->reloc_size = (reinterpret_cast<byte*>(buffer_) + buffer_size_) -
584 reloc_info_writer.pos();
590 void Assembler::Align(int m) {
591 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
592 while ((pc_offset() & (m - 1)) != 0) {
598 void Assembler::CheckLabelLinkChain(Label const * label) {
600 if (label->is_linked()) {
601 static const int kMaxLinksToCheck = 64; // Avoid O(n2) behaviour.
602 int links_checked = 0;
603 int linkoffset = label->pos();
604 bool end_of_chain = false;
605 while (!end_of_chain) {
606 if (++links_checked > kMaxLinksToCheck) break;
607 Instruction * link = InstructionAt(linkoffset);
608 int linkpcoffset = link->ImmPCOffset();
609 int prevlinkoffset = linkoffset + linkpcoffset;
611 end_of_chain = (linkoffset == prevlinkoffset);
612 linkoffset = linkoffset + linkpcoffset;
619 void Assembler::RemoveBranchFromLabelLinkChain(Instruction* branch,
621 Instruction* label_veneer) {
622 DCHECK(label->is_linked());
624 CheckLabelLinkChain(label);
626 Instruction* link = InstructionAt(label->pos());
627 Instruction* prev_link = link;
628 Instruction* next_link;
629 bool end_of_chain = false;
631 while (link != branch && !end_of_chain) {
632 next_link = link->ImmPCOffsetTarget();
633 end_of_chain = (link == next_link);
638 DCHECK(branch == link);
639 next_link = branch->ImmPCOffsetTarget();
641 if (branch == prev_link) {
642 // The branch is the first instruction in the chain.
643 if (branch == next_link) {
644 // It is also the last instruction in the chain, so it is the only branch
645 // currently referring to this label.
648 label->link_to(reinterpret_cast<byte*>(next_link) - buffer_);
651 } else if (branch == next_link) {
652 // The branch is the last (but not also the first) instruction in the chain.
653 prev_link->SetImmPCOffsetTarget(prev_link);
656 // The branch is in the middle of the chain.
657 if (prev_link->IsTargetInImmPCOffsetRange(next_link)) {
658 prev_link->SetImmPCOffsetTarget(next_link);
659 } else if (label_veneer != NULL) {
660 // Use the veneer for all previous links in the chain.
661 prev_link->SetImmPCOffsetTarget(prev_link);
663 end_of_chain = false;
665 while (!end_of_chain) {
666 next_link = link->ImmPCOffsetTarget();
667 end_of_chain = (link == next_link);
668 link->SetImmPCOffsetTarget(label_veneer);
672 // The assert below will fire.
673 // Some other work could be attempted to fix up the chain, but it would be
674 // rather complicated. If we crash here, we may want to consider using an
675 // other mechanism than a chain of branches.
677 // Note that this situation currently should not happen, as we always call
678 // this function with a veneer to the target label.
679 // However this could happen with a MacroAssembler in the following state:
683 // Tbz(label); // First tbz. Pointing to unconditional branch.
685 // Tbz(label); // Second tbz. Pointing to the first tbz.
687 // and this function is called to remove the first tbz from the label link
688 // chain. Since tbz has a range of +-32KB, the second tbz cannot point to
689 // the unconditional branch.
690 CHECK(prev_link->IsTargetInImmPCOffsetRange(next_link));
695 CheckLabelLinkChain(label);
699 void Assembler::bind(Label* label) {
700 // Bind label to the address at pc_. All instructions (most likely branches)
701 // that are linked to this label will be updated to point to the newly-bound
704 DCHECK(!label->is_near_linked());
705 DCHECK(!label->is_bound());
707 DeleteUnresolvedBranchInfoForLabel(label);
709 // If the label is linked, the link chain looks something like this:
711 // |--I----I-------I-------L
712 // |---------------------->| pc_offset
713 // |-------------->| linkoffset = label->pos()
714 // |<------| link->ImmPCOffset()
715 // |------>| prevlinkoffset = linkoffset + link->ImmPCOffset()
717 // On each iteration, the last link is updated and then removed from the
718 // chain until only one remains. At that point, the label is bound.
720 // If the label is not linked, no preparation is required before binding.
721 while (label->is_linked()) {
722 int linkoffset = label->pos();
723 Instruction* link = InstructionAt(linkoffset);
724 int prevlinkoffset = linkoffset + link->ImmPCOffset();
726 CheckLabelLinkChain(label);
728 DCHECK(linkoffset >= 0);
729 DCHECK(linkoffset < pc_offset());
730 DCHECK((linkoffset > prevlinkoffset) ||
731 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain));
732 DCHECK(prevlinkoffset >= 0);
734 // Update the link to point to the label.
735 if (link->IsUnresolvedInternalReference()) {
736 // Internal references do not get patched to an instruction but directly
738 internal_reference_positions_.push_back(linkoffset);
739 PatchingAssembler patcher(link, 2);
740 patcher.dc64(reinterpret_cast<uintptr_t>(pc_));
742 link->SetImmPCOffsetTarget(reinterpret_cast<Instruction*>(pc_));
745 // Link the label to the previous link in the chain.
746 if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) {
747 // We hit kStartOfLabelLinkChain, so the chain is fully processed.
750 // Update the label for the next iteration.
751 label->link_to(prevlinkoffset);
754 label->bind_to(pc_offset());
756 DCHECK(label->is_bound());
757 DCHECK(!label->is_linked());
761 int Assembler::LinkAndGetByteOffsetTo(Label* label) {
762 DCHECK(sizeof(*pc_) == 1);
763 CheckLabelLinkChain(label);
766 if (label->is_bound()) {
767 // The label is bound, so it does not need to be updated. Referring
768 // instructions must link directly to the label as they will not be
771 // In this case, label->pos() returns the offset of the label from the
772 // start of the buffer.
774 // Note that offset can be zero for self-referential instructions. (This
775 // could be useful for ADR, for example.)
776 offset = label->pos() - pc_offset();
779 if (label->is_linked()) {
780 // The label is linked, so the referring instruction should be added onto
781 // the end of the label's link chain.
783 // In this case, label->pos() returns the offset of the last linked
784 // instruction from the start of the buffer.
785 offset = label->pos() - pc_offset();
786 DCHECK(offset != kStartOfLabelLinkChain);
787 // Note that the offset here needs to be PC-relative only so that the
788 // first instruction in a buffer can link to an unbound label. Otherwise,
789 // the offset would be 0 for this case, and 0 is reserved for
790 // kStartOfLabelLinkChain.
792 // The label is unused, so it now becomes linked and the referring
793 // instruction is at the start of the new link chain.
794 offset = kStartOfLabelLinkChain;
796 // The instruction at pc is now the last link in the label's chain.
797 label->link_to(pc_offset());
804 void Assembler::DeleteUnresolvedBranchInfoForLabelTraverse(Label* label) {
805 DCHECK(label->is_linked());
806 CheckLabelLinkChain(label);
808 int link_offset = label->pos();
810 bool end_of_chain = false;
812 while (!end_of_chain) {
813 Instruction * link = InstructionAt(link_offset);
814 link_pcoffset = link->ImmPCOffset();
816 // ADR instructions are not handled by veneers.
817 if (link->IsImmBranch()) {
818 int max_reachable_pc = InstructionOffset(link) +
819 Instruction::ImmBranchRange(link->BranchType());
820 typedef std::multimap<int, FarBranchInfo>::iterator unresolved_info_it;
821 std::pair<unresolved_info_it, unresolved_info_it> range;
822 range = unresolved_branches_.equal_range(max_reachable_pc);
823 unresolved_info_it it;
824 for (it = range.first; it != range.second; ++it) {
825 if (it->second.pc_offset_ == link_offset) {
826 unresolved_branches_.erase(it);
832 end_of_chain = (link_pcoffset == 0);
833 link_offset = link_offset + link_pcoffset;
838 void Assembler::DeleteUnresolvedBranchInfoForLabel(Label* label) {
839 if (unresolved_branches_.empty()) {
840 DCHECK(next_veneer_pool_check_ == kMaxInt);
844 if (label->is_linked()) {
845 // Branches to this label will be resolved when the label is bound, normally
846 // just after all the associated info has been deleted.
847 DeleteUnresolvedBranchInfoForLabelTraverse(label);
849 if (unresolved_branches_.empty()) {
850 next_veneer_pool_check_ = kMaxInt;
852 next_veneer_pool_check_ =
853 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
858 void Assembler::StartBlockConstPool() {
859 if (const_pool_blocked_nesting_++ == 0) {
860 // Prevent constant pool checks happening by setting the next check to
861 // the biggest possible offset.
862 next_constant_pool_check_ = kMaxInt;
867 void Assembler::EndBlockConstPool() {
868 if (--const_pool_blocked_nesting_ == 0) {
869 // Check the constant pool hasn't been blocked for too long.
870 DCHECK(pc_offset() < constpool_.MaxPcOffset());
872 // * no_const_pool_before_ >= next_constant_pool_check_ and the emission is
874 // * no_const_pool_before_ < next_constant_pool_check_ and the next emit
875 // will trigger a check.
876 next_constant_pool_check_ = no_const_pool_before_;
881 bool Assembler::is_const_pool_blocked() const {
882 return (const_pool_blocked_nesting_ > 0) ||
883 (pc_offset() < no_const_pool_before_);
887 bool Assembler::IsConstantPoolAt(Instruction* instr) {
888 // The constant pool marker is made of two instructions. These instructions
889 // will never be emitted by the JIT, so checking for the first one is enough:
890 // 0: ldr xzr, #<size of pool>
891 bool result = instr->IsLdrLiteralX() && (instr->Rt() == xzr.code());
893 // It is still worth asserting the marker is complete.
895 DCHECK(!result || (instr->following()->IsBranchAndLinkToRegister() &&
896 instr->following()->Rn() == xzr.code()));
902 int Assembler::ConstantPoolSizeAt(Instruction* instr) {
904 // Assembler::debug() embeds constants directly into the instruction stream.
905 // Although this is not a genuine constant pool, treat it like one to avoid
906 // disassembling the constants.
907 if ((instr->Mask(ExceptionMask) == HLT) &&
908 (instr->ImmException() == kImmExceptionIsDebug)) {
909 const char* message =
910 reinterpret_cast<const char*>(
911 instr->InstructionAtOffset(kDebugMessageOffset));
912 int size = kDebugMessageOffset + strlen(message) + 1;
913 return RoundUp(size, kInstructionSize) / kInstructionSize;
915 // Same for printf support, see MacroAssembler::CallPrintf().
916 if ((instr->Mask(ExceptionMask) == HLT) &&
917 (instr->ImmException() == kImmExceptionIsPrintf)) {
918 return kPrintfLength / kInstructionSize;
921 if (IsConstantPoolAt(instr)) {
922 return instr->ImmLLiteral();
929 void Assembler::EmitPoolGuard() {
930 // We must generate only one instruction as this is used in scopes that
931 // control the size of the code generated.
936 void Assembler::StartBlockVeneerPool() {
937 ++veneer_pool_blocked_nesting_;
941 void Assembler::EndBlockVeneerPool() {
942 if (--veneer_pool_blocked_nesting_ == 0) {
943 // Check the veneer pool hasn't been blocked for too long.
944 DCHECK(unresolved_branches_.empty() ||
945 (pc_offset() < unresolved_branches_first_limit()));
950 void Assembler::br(const Register& xn) {
951 positions_recorder()->WriteRecordedPositions();
952 DCHECK(xn.Is64Bits());
957 void Assembler::blr(const Register& xn) {
958 positions_recorder()->WriteRecordedPositions();
959 DCHECK(xn.Is64Bits());
960 // The pattern 'blr xzr' is used as a guard to detect when execution falls
961 // through the constant pool. It should not be emitted.
967 void Assembler::ret(const Register& xn) {
968 positions_recorder()->WriteRecordedPositions();
969 DCHECK(xn.Is64Bits());
974 void Assembler::b(int imm26) {
975 Emit(B | ImmUncondBranch(imm26));
979 void Assembler::b(Label* label) {
980 positions_recorder()->WriteRecordedPositions();
981 b(LinkAndGetInstructionOffsetTo(label));
985 void Assembler::b(int imm19, Condition cond) {
986 Emit(B_cond | ImmCondBranch(imm19) | cond);
990 void Assembler::b(Label* label, Condition cond) {
991 positions_recorder()->WriteRecordedPositions();
992 b(LinkAndGetInstructionOffsetTo(label), cond);
996 void Assembler::bl(int imm26) {
997 positions_recorder()->WriteRecordedPositions();
998 Emit(BL | ImmUncondBranch(imm26));
1002 void Assembler::bl(Label* label) {
1003 positions_recorder()->WriteRecordedPositions();
1004 bl(LinkAndGetInstructionOffsetTo(label));
1008 void Assembler::cbz(const Register& rt,
1010 positions_recorder()->WriteRecordedPositions();
1011 Emit(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt));
1015 void Assembler::cbz(const Register& rt,
1017 positions_recorder()->WriteRecordedPositions();
1018 cbz(rt, LinkAndGetInstructionOffsetTo(label));
1022 void Assembler::cbnz(const Register& rt,
1024 positions_recorder()->WriteRecordedPositions();
1025 Emit(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt));
1029 void Assembler::cbnz(const Register& rt,
1031 positions_recorder()->WriteRecordedPositions();
1032 cbnz(rt, LinkAndGetInstructionOffsetTo(label));
1036 void Assembler::tbz(const Register& rt,
1039 positions_recorder()->WriteRecordedPositions();
1040 DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
1041 Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
1045 void Assembler::tbz(const Register& rt,
1048 positions_recorder()->WriteRecordedPositions();
1049 tbz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
1053 void Assembler::tbnz(const Register& rt,
1056 positions_recorder()->WriteRecordedPositions();
1057 DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
1058 Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
1062 void Assembler::tbnz(const Register& rt,
1065 positions_recorder()->WriteRecordedPositions();
1066 tbnz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
1070 void Assembler::adr(const Register& rd, int imm21) {
1071 DCHECK(rd.Is64Bits());
1072 Emit(ADR | ImmPCRelAddress(imm21) | Rd(rd));
1076 void Assembler::adr(const Register& rd, Label* label) {
1077 adr(rd, LinkAndGetByteOffsetTo(label));
1081 void Assembler::add(const Register& rd,
1083 const Operand& operand) {
1084 AddSub(rd, rn, operand, LeaveFlags, ADD);
1088 void Assembler::adds(const Register& rd,
1090 const Operand& operand) {
1091 AddSub(rd, rn, operand, SetFlags, ADD);
1095 void Assembler::cmn(const Register& rn,
1096 const Operand& operand) {
1097 Register zr = AppropriateZeroRegFor(rn);
1098 adds(zr, rn, operand);
1102 void Assembler::sub(const Register& rd,
1104 const Operand& operand) {
1105 AddSub(rd, rn, operand, LeaveFlags, SUB);
1109 void Assembler::subs(const Register& rd,
1111 const Operand& operand) {
1112 AddSub(rd, rn, operand, SetFlags, SUB);
1116 void Assembler::cmp(const Register& rn, const Operand& operand) {
1117 Register zr = AppropriateZeroRegFor(rn);
1118 subs(zr, rn, operand);
1122 void Assembler::neg(const Register& rd, const Operand& operand) {
1123 Register zr = AppropriateZeroRegFor(rd);
1124 sub(rd, zr, operand);
1128 void Assembler::negs(const Register& rd, const Operand& operand) {
1129 Register zr = AppropriateZeroRegFor(rd);
1130 subs(rd, zr, operand);
1134 void Assembler::adc(const Register& rd,
1136 const Operand& operand) {
1137 AddSubWithCarry(rd, rn, operand, LeaveFlags, ADC);
1141 void Assembler::adcs(const Register& rd,
1143 const Operand& operand) {
1144 AddSubWithCarry(rd, rn, operand, SetFlags, ADC);
1148 void Assembler::sbc(const Register& rd,
1150 const Operand& operand) {
1151 AddSubWithCarry(rd, rn, operand, LeaveFlags, SBC);
1155 void Assembler::sbcs(const Register& rd,
1157 const Operand& operand) {
1158 AddSubWithCarry(rd, rn, operand, SetFlags, SBC);
1162 void Assembler::ngc(const Register& rd, const Operand& operand) {
1163 Register zr = AppropriateZeroRegFor(rd);
1164 sbc(rd, zr, operand);
1168 void Assembler::ngcs(const Register& rd, const Operand& operand) {
1169 Register zr = AppropriateZeroRegFor(rd);
1170 sbcs(rd, zr, operand);
1174 // Logical instructions.
1175 void Assembler::and_(const Register& rd,
1177 const Operand& operand) {
1178 Logical(rd, rn, operand, AND);
1182 void Assembler::ands(const Register& rd,
1184 const Operand& operand) {
1185 Logical(rd, rn, operand, ANDS);
1189 void Assembler::tst(const Register& rn,
1190 const Operand& operand) {
1191 ands(AppropriateZeroRegFor(rn), rn, operand);
1195 void Assembler::bic(const Register& rd,
1197 const Operand& operand) {
1198 Logical(rd, rn, operand, BIC);
1202 void Assembler::bics(const Register& rd,
1204 const Operand& operand) {
1205 Logical(rd, rn, operand, BICS);
1209 void Assembler::orr(const Register& rd,
1211 const Operand& operand) {
1212 Logical(rd, rn, operand, ORR);
1216 void Assembler::orn(const Register& rd,
1218 const Operand& operand) {
1219 Logical(rd, rn, operand, ORN);
1223 void Assembler::eor(const Register& rd,
1225 const Operand& operand) {
1226 Logical(rd, rn, operand, EOR);
1230 void Assembler::eon(const Register& rd,
1232 const Operand& operand) {
1233 Logical(rd, rn, operand, EON);
1237 void Assembler::lslv(const Register& rd,
1239 const Register& rm) {
1240 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1241 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1242 Emit(SF(rd) | LSLV | Rm(rm) | Rn(rn) | Rd(rd));
1246 void Assembler::lsrv(const Register& rd,
1248 const Register& rm) {
1249 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1250 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1251 Emit(SF(rd) | LSRV | Rm(rm) | Rn(rn) | Rd(rd));
1255 void Assembler::asrv(const Register& rd,
1257 const Register& rm) {
1258 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1259 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1260 Emit(SF(rd) | ASRV | Rm(rm) | Rn(rn) | Rd(rd));
1264 void Assembler::rorv(const Register& rd,
1266 const Register& rm) {
1267 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1268 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1269 Emit(SF(rd) | RORV | Rm(rm) | Rn(rn) | Rd(rd));
1273 // Bitfield operations.
1274 void Assembler::bfm(const Register& rd,
1278 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1279 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
1280 Emit(SF(rd) | BFM | N |
1281 ImmR(immr, rd.SizeInBits()) |
1282 ImmS(imms, rn.SizeInBits()) |
1287 void Assembler::sbfm(const Register& rd,
1291 DCHECK(rd.Is64Bits() || rn.Is32Bits());
1292 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
1293 Emit(SF(rd) | SBFM | N |
1294 ImmR(immr, rd.SizeInBits()) |
1295 ImmS(imms, rn.SizeInBits()) |
1300 void Assembler::ubfm(const Register& rd,
1304 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1305 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
1306 Emit(SF(rd) | UBFM | N |
1307 ImmR(immr, rd.SizeInBits()) |
1308 ImmS(imms, rn.SizeInBits()) |
1313 void Assembler::extr(const Register& rd,
1317 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1318 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1319 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
1320 Emit(SF(rd) | EXTR | N | Rm(rm) |
1321 ImmS(lsb, rn.SizeInBits()) | Rn(rn) | Rd(rd));
1325 void Assembler::csel(const Register& rd,
1329 ConditionalSelect(rd, rn, rm, cond, CSEL);
1333 void Assembler::csinc(const Register& rd,
1337 ConditionalSelect(rd, rn, rm, cond, CSINC);
1341 void Assembler::csinv(const Register& rd,
1345 ConditionalSelect(rd, rn, rm, cond, CSINV);
1349 void Assembler::csneg(const Register& rd,
1353 ConditionalSelect(rd, rn, rm, cond, CSNEG);
1357 void Assembler::cset(const Register &rd, Condition cond) {
1358 DCHECK((cond != al) && (cond != nv));
1359 Register zr = AppropriateZeroRegFor(rd);
1360 csinc(rd, zr, zr, NegateCondition(cond));
1364 void Assembler::csetm(const Register &rd, Condition cond) {
1365 DCHECK((cond != al) && (cond != nv));
1366 Register zr = AppropriateZeroRegFor(rd);
1367 csinv(rd, zr, zr, NegateCondition(cond));
1371 void Assembler::cinc(const Register &rd, const Register &rn, Condition cond) {
1372 DCHECK((cond != al) && (cond != nv));
1373 csinc(rd, rn, rn, NegateCondition(cond));
1377 void Assembler::cinv(const Register &rd, const Register &rn, Condition cond) {
1378 DCHECK((cond != al) && (cond != nv));
1379 csinv(rd, rn, rn, NegateCondition(cond));
1383 void Assembler::cneg(const Register &rd, const Register &rn, Condition cond) {
1384 DCHECK((cond != al) && (cond != nv));
1385 csneg(rd, rn, rn, NegateCondition(cond));
1389 void Assembler::ConditionalSelect(const Register& rd,
1393 ConditionalSelectOp op) {
1394 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1395 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1396 Emit(SF(rd) | op | Rm(rm) | Cond(cond) | Rn(rn) | Rd(rd));
1400 void Assembler::ccmn(const Register& rn,
1401 const Operand& operand,
1404 ConditionalCompare(rn, operand, nzcv, cond, CCMN);
1408 void Assembler::ccmp(const Register& rn,
1409 const Operand& operand,
1412 ConditionalCompare(rn, operand, nzcv, cond, CCMP);
1416 void Assembler::DataProcessing3Source(const Register& rd,
1420 DataProcessing3SourceOp op) {
1421 Emit(SF(rd) | op | Rm(rm) | Ra(ra) | Rn(rn) | Rd(rd));
1425 void Assembler::mul(const Register& rd,
1427 const Register& rm) {
1428 DCHECK(AreSameSizeAndType(rd, rn, rm));
1429 Register zr = AppropriateZeroRegFor(rn);
1430 DataProcessing3Source(rd, rn, rm, zr, MADD);
1434 void Assembler::madd(const Register& rd,
1437 const Register& ra) {
1438 DCHECK(AreSameSizeAndType(rd, rn, rm, ra));
1439 DataProcessing3Source(rd, rn, rm, ra, MADD);
1443 void Assembler::mneg(const Register& rd,
1445 const Register& rm) {
1446 DCHECK(AreSameSizeAndType(rd, rn, rm));
1447 Register zr = AppropriateZeroRegFor(rn);
1448 DataProcessing3Source(rd, rn, rm, zr, MSUB);
1452 void Assembler::msub(const Register& rd,
1455 const Register& ra) {
1456 DCHECK(AreSameSizeAndType(rd, rn, rm, ra));
1457 DataProcessing3Source(rd, rn, rm, ra, MSUB);
1461 void Assembler::smaddl(const Register& rd,
1464 const Register& ra) {
1465 DCHECK(rd.Is64Bits() && ra.Is64Bits());
1466 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1467 DataProcessing3Source(rd, rn, rm, ra, SMADDL_x);
1471 void Assembler::smsubl(const Register& rd,
1474 const Register& ra) {
1475 DCHECK(rd.Is64Bits() && ra.Is64Bits());
1476 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1477 DataProcessing3Source(rd, rn, rm, ra, SMSUBL_x);
1481 void Assembler::umaddl(const Register& rd,
1484 const Register& ra) {
1485 DCHECK(rd.Is64Bits() && ra.Is64Bits());
1486 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1487 DataProcessing3Source(rd, rn, rm, ra, UMADDL_x);
1491 void Assembler::umsubl(const Register& rd,
1494 const Register& ra) {
1495 DCHECK(rd.Is64Bits() && ra.Is64Bits());
1496 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1497 DataProcessing3Source(rd, rn, rm, ra, UMSUBL_x);
1501 void Assembler::smull(const Register& rd,
1503 const Register& rm) {
1504 DCHECK(rd.Is64Bits());
1505 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1506 DataProcessing3Source(rd, rn, rm, xzr, SMADDL_x);
1510 void Assembler::smulh(const Register& rd,
1512 const Register& rm) {
1513 DCHECK(AreSameSizeAndType(rd, rn, rm));
1514 DataProcessing3Source(rd, rn, rm, xzr, SMULH_x);
1518 void Assembler::sdiv(const Register& rd,
1520 const Register& rm) {
1521 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1522 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1523 Emit(SF(rd) | SDIV | Rm(rm) | Rn(rn) | Rd(rd));
1527 void Assembler::udiv(const Register& rd,
1529 const Register& rm) {
1530 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1531 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1532 Emit(SF(rd) | UDIV | Rm(rm) | Rn(rn) | Rd(rd));
1536 void Assembler::rbit(const Register& rd,
1537 const Register& rn) {
1538 DataProcessing1Source(rd, rn, RBIT);
1542 void Assembler::rev16(const Register& rd,
1543 const Register& rn) {
1544 DataProcessing1Source(rd, rn, REV16);
1548 void Assembler::rev32(const Register& rd,
1549 const Register& rn) {
1550 DCHECK(rd.Is64Bits());
1551 DataProcessing1Source(rd, rn, REV);
1555 void Assembler::rev(const Register& rd,
1556 const Register& rn) {
1557 DataProcessing1Source(rd, rn, rd.Is64Bits() ? REV_x : REV_w);
1561 void Assembler::clz(const Register& rd,
1562 const Register& rn) {
1563 DataProcessing1Source(rd, rn, CLZ);
1567 void Assembler::cls(const Register& rd,
1568 const Register& rn) {
1569 DataProcessing1Source(rd, rn, CLS);
1573 void Assembler::ldp(const CPURegister& rt,
1574 const CPURegister& rt2,
1575 const MemOperand& src) {
1576 LoadStorePair(rt, rt2, src, LoadPairOpFor(rt, rt2));
1580 void Assembler::stp(const CPURegister& rt,
1581 const CPURegister& rt2,
1582 const MemOperand& dst) {
1583 LoadStorePair(rt, rt2, dst, StorePairOpFor(rt, rt2));
1587 void Assembler::ldpsw(const Register& rt,
1588 const Register& rt2,
1589 const MemOperand& src) {
1590 DCHECK(rt.Is64Bits());
1591 LoadStorePair(rt, rt2, src, LDPSW_x);
1595 void Assembler::LoadStorePair(const CPURegister& rt,
1596 const CPURegister& rt2,
1597 const MemOperand& addr,
1598 LoadStorePairOp op) {
1599 // 'rt' and 'rt2' can only be aliased for stores.
1600 DCHECK(((op & LoadStorePairLBit) == 0) || !rt.Is(rt2));
1601 DCHECK(AreSameSizeAndType(rt, rt2));
1603 Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
1604 ImmLSPair(addr.offset(), CalcLSPairDataSize(op));
1607 if (addr.IsImmediateOffset()) {
1608 addrmodeop = LoadStorePairOffsetFixed;
1610 // Pre-index and post-index modes.
1611 DCHECK(!rt.Is(addr.base()));
1612 DCHECK(!rt2.Is(addr.base()));
1613 DCHECK(addr.offset() != 0);
1614 if (addr.IsPreIndex()) {
1615 addrmodeop = LoadStorePairPreIndexFixed;
1617 DCHECK(addr.IsPostIndex());
1618 addrmodeop = LoadStorePairPostIndexFixed;
1621 Emit(addrmodeop | memop);
1625 void Assembler::ldnp(const CPURegister& rt,
1626 const CPURegister& rt2,
1627 const MemOperand& src) {
1628 LoadStorePairNonTemporal(rt, rt2, src,
1629 LoadPairNonTemporalOpFor(rt, rt2));
1633 void Assembler::stnp(const CPURegister& rt,
1634 const CPURegister& rt2,
1635 const MemOperand& dst) {
1636 LoadStorePairNonTemporal(rt, rt2, dst,
1637 StorePairNonTemporalOpFor(rt, rt2));
1641 void Assembler::LoadStorePairNonTemporal(const CPURegister& rt,
1642 const CPURegister& rt2,
1643 const MemOperand& addr,
1644 LoadStorePairNonTemporalOp op) {
1645 DCHECK(!rt.Is(rt2));
1646 DCHECK(AreSameSizeAndType(rt, rt2));
1647 DCHECK(addr.IsImmediateOffset());
1649 LSDataSize size = CalcLSPairDataSize(
1650 static_cast<LoadStorePairOp>(op & LoadStorePairMask));
1651 Emit(op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
1652 ImmLSPair(addr.offset(), size));
1656 // Memory instructions.
1657 void Assembler::ldrb(const Register& rt, const MemOperand& src) {
1658 LoadStore(rt, src, LDRB_w);
1662 void Assembler::strb(const Register& rt, const MemOperand& dst) {
1663 LoadStore(rt, dst, STRB_w);
1667 void Assembler::ldrsb(const Register& rt, const MemOperand& src) {
1668 LoadStore(rt, src, rt.Is64Bits() ? LDRSB_x : LDRSB_w);
1672 void Assembler::ldrh(const Register& rt, const MemOperand& src) {
1673 LoadStore(rt, src, LDRH_w);
1677 void Assembler::strh(const Register& rt, const MemOperand& dst) {
1678 LoadStore(rt, dst, STRH_w);
1682 void Assembler::ldrsh(const Register& rt, const MemOperand& src) {
1683 LoadStore(rt, src, rt.Is64Bits() ? LDRSH_x : LDRSH_w);
1687 void Assembler::ldr(const CPURegister& rt, const MemOperand& src) {
1688 LoadStore(rt, src, LoadOpFor(rt));
1692 void Assembler::str(const CPURegister& rt, const MemOperand& src) {
1693 LoadStore(rt, src, StoreOpFor(rt));
1697 void Assembler::ldrsw(const Register& rt, const MemOperand& src) {
1698 DCHECK(rt.Is64Bits());
1699 LoadStore(rt, src, LDRSW_x);
1703 void Assembler::ldr_pcrel(const CPURegister& rt, int imm19) {
1704 // The pattern 'ldr xzr, #offset' is used to indicate the beginning of a
1705 // constant pool. It should not be emitted.
1706 DCHECK(!rt.IsZero());
1707 Emit(LoadLiteralOpFor(rt) | ImmLLiteral(imm19) | Rt(rt));
1711 void Assembler::ldr(const CPURegister& rt, const Immediate& imm) {
1712 // Currently we only support 64-bit literals.
1713 DCHECK(rt.Is64Bits());
1715 RecordRelocInfo(imm.rmode(), imm.value());
1716 BlockConstPoolFor(1);
1717 // The load will be patched when the constpool is emitted, patching code
1718 // expect a load literal with offset 0.
1723 void Assembler::mov(const Register& rd, const Register& rm) {
1724 // Moves involving the stack pointer are encoded as add immediate with
1725 // second operand of zero. Otherwise, orr with first operand zr is
1727 if (rd.IsSP() || rm.IsSP()) {
1730 orr(rd, AppropriateZeroRegFor(rd), rm);
1735 void Assembler::mvn(const Register& rd, const Operand& operand) {
1736 orn(rd, AppropriateZeroRegFor(rd), operand);
1740 void Assembler::mrs(const Register& rt, SystemRegister sysreg) {
1741 DCHECK(rt.Is64Bits());
1742 Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt));
1746 void Assembler::msr(SystemRegister sysreg, const Register& rt) {
1747 DCHECK(rt.Is64Bits());
1748 Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg));
1752 void Assembler::hint(SystemHint code) {
1753 Emit(HINT | ImmHint(code) | Rt(xzr));
1757 void Assembler::dmb(BarrierDomain domain, BarrierType type) {
1758 Emit(DMB | ImmBarrierDomain(domain) | ImmBarrierType(type));
1762 void Assembler::dsb(BarrierDomain domain, BarrierType type) {
1763 Emit(DSB | ImmBarrierDomain(domain) | ImmBarrierType(type));
1767 void Assembler::isb() {
1768 Emit(ISB | ImmBarrierDomain(FullSystem) | ImmBarrierType(BarrierAll));
1772 void Assembler::fmov(FPRegister fd, double imm) {
1773 DCHECK(fd.Is64Bits());
1774 DCHECK(IsImmFP64(imm));
1775 Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm));
1779 void Assembler::fmov(FPRegister fd, float imm) {
1780 DCHECK(fd.Is32Bits());
1781 DCHECK(IsImmFP32(imm));
1782 Emit(FMOV_s_imm | Rd(fd) | ImmFP32(imm));
1786 void Assembler::fmov(Register rd, FPRegister fn) {
1787 DCHECK(rd.SizeInBits() == fn.SizeInBits());
1788 FPIntegerConvertOp op = rd.Is32Bits() ? FMOV_ws : FMOV_xd;
1789 Emit(op | Rd(rd) | Rn(fn));
1793 void Assembler::fmov(FPRegister fd, Register rn) {
1794 DCHECK(fd.SizeInBits() == rn.SizeInBits());
1795 FPIntegerConvertOp op = fd.Is32Bits() ? FMOV_sw : FMOV_dx;
1796 Emit(op | Rd(fd) | Rn(rn));
1800 void Assembler::fmov(FPRegister fd, FPRegister fn) {
1801 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1802 Emit(FPType(fd) | FMOV | Rd(fd) | Rn(fn));
1806 void Assembler::fadd(const FPRegister& fd,
1807 const FPRegister& fn,
1808 const FPRegister& fm) {
1809 FPDataProcessing2Source(fd, fn, fm, FADD);
1813 void Assembler::fsub(const FPRegister& fd,
1814 const FPRegister& fn,
1815 const FPRegister& fm) {
1816 FPDataProcessing2Source(fd, fn, fm, FSUB);
1820 void Assembler::fmul(const FPRegister& fd,
1821 const FPRegister& fn,
1822 const FPRegister& fm) {
1823 FPDataProcessing2Source(fd, fn, fm, FMUL);
1827 void Assembler::fmadd(const FPRegister& fd,
1828 const FPRegister& fn,
1829 const FPRegister& fm,
1830 const FPRegister& fa) {
1831 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMADD_s : FMADD_d);
1835 void Assembler::fmsub(const FPRegister& fd,
1836 const FPRegister& fn,
1837 const FPRegister& fm,
1838 const FPRegister& fa) {
1839 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMSUB_s : FMSUB_d);
1843 void Assembler::fnmadd(const FPRegister& fd,
1844 const FPRegister& fn,
1845 const FPRegister& fm,
1846 const FPRegister& fa) {
1847 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMADD_s : FNMADD_d);
1851 void Assembler::fnmsub(const FPRegister& fd,
1852 const FPRegister& fn,
1853 const FPRegister& fm,
1854 const FPRegister& fa) {
1855 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMSUB_s : FNMSUB_d);
1859 void Assembler::fdiv(const FPRegister& fd,
1860 const FPRegister& fn,
1861 const FPRegister& fm) {
1862 FPDataProcessing2Source(fd, fn, fm, FDIV);
1866 void Assembler::fmax(const FPRegister& fd,
1867 const FPRegister& fn,
1868 const FPRegister& fm) {
1869 FPDataProcessing2Source(fd, fn, fm, FMAX);
1873 void Assembler::fmaxnm(const FPRegister& fd,
1874 const FPRegister& fn,
1875 const FPRegister& fm) {
1876 FPDataProcessing2Source(fd, fn, fm, FMAXNM);
1880 void Assembler::fmin(const FPRegister& fd,
1881 const FPRegister& fn,
1882 const FPRegister& fm) {
1883 FPDataProcessing2Source(fd, fn, fm, FMIN);
1887 void Assembler::fminnm(const FPRegister& fd,
1888 const FPRegister& fn,
1889 const FPRegister& fm) {
1890 FPDataProcessing2Source(fd, fn, fm, FMINNM);
1894 void Assembler::fabs(const FPRegister& fd,
1895 const FPRegister& fn) {
1896 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1897 FPDataProcessing1Source(fd, fn, FABS);
1901 void Assembler::fneg(const FPRegister& fd,
1902 const FPRegister& fn) {
1903 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1904 FPDataProcessing1Source(fd, fn, FNEG);
1908 void Assembler::fsqrt(const FPRegister& fd,
1909 const FPRegister& fn) {
1910 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1911 FPDataProcessing1Source(fd, fn, FSQRT);
1915 void Assembler::frinta(const FPRegister& fd,
1916 const FPRegister& fn) {
1917 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1918 FPDataProcessing1Source(fd, fn, FRINTA);
1922 void Assembler::frintm(const FPRegister& fd,
1923 const FPRegister& fn) {
1924 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1925 FPDataProcessing1Source(fd, fn, FRINTM);
1929 void Assembler::frintn(const FPRegister& fd,
1930 const FPRegister& fn) {
1931 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1932 FPDataProcessing1Source(fd, fn, FRINTN);
1936 void Assembler::frintp(const FPRegister& fd, const FPRegister& fn) {
1937 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1938 FPDataProcessing1Source(fd, fn, FRINTP);
1942 void Assembler::frintz(const FPRegister& fd,
1943 const FPRegister& fn) {
1944 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1945 FPDataProcessing1Source(fd, fn, FRINTZ);
1949 void Assembler::fcmp(const FPRegister& fn,
1950 const FPRegister& fm) {
1951 DCHECK(fn.SizeInBits() == fm.SizeInBits());
1952 Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn));
1956 void Assembler::fcmp(const FPRegister& fn,
1959 // Although the fcmp instruction can strictly only take an immediate value of
1960 // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't
1961 // affect the result of the comparison.
1962 DCHECK(value == 0.0);
1963 Emit(FPType(fn) | FCMP_zero | Rn(fn));
1967 void Assembler::fccmp(const FPRegister& fn,
1968 const FPRegister& fm,
1971 DCHECK(fn.SizeInBits() == fm.SizeInBits());
1972 Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv));
1976 void Assembler::fcsel(const FPRegister& fd,
1977 const FPRegister& fn,
1978 const FPRegister& fm,
1980 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1981 DCHECK(fd.SizeInBits() == fm.SizeInBits());
1982 Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd));
1986 void Assembler::FPConvertToInt(const Register& rd,
1987 const FPRegister& fn,
1988 FPIntegerConvertOp op) {
1989 Emit(SF(rd) | FPType(fn) | op | Rn(fn) | Rd(rd));
1993 void Assembler::fcvt(const FPRegister& fd,
1994 const FPRegister& fn) {
1995 if (fd.Is64Bits()) {
1996 // Convert float to double.
1997 DCHECK(fn.Is32Bits());
1998 FPDataProcessing1Source(fd, fn, FCVT_ds);
2000 // Convert double to float.
2001 DCHECK(fn.Is64Bits());
2002 FPDataProcessing1Source(fd, fn, FCVT_sd);
2007 void Assembler::fcvtau(const Register& rd, const FPRegister& fn) {
2008 FPConvertToInt(rd, fn, FCVTAU);
2012 void Assembler::fcvtas(const Register& rd, const FPRegister& fn) {
2013 FPConvertToInt(rd, fn, FCVTAS);
2017 void Assembler::fcvtmu(const Register& rd, const FPRegister& fn) {
2018 FPConvertToInt(rd, fn, FCVTMU);
2022 void Assembler::fcvtms(const Register& rd, const FPRegister& fn) {
2023 FPConvertToInt(rd, fn, FCVTMS);
2027 void Assembler::fcvtnu(const Register& rd, const FPRegister& fn) {
2028 FPConvertToInt(rd, fn, FCVTNU);
2032 void Assembler::fcvtns(const Register& rd, const FPRegister& fn) {
2033 FPConvertToInt(rd, fn, FCVTNS);
2037 void Assembler::fcvtzu(const Register& rd, const FPRegister& fn) {
2038 FPConvertToInt(rd, fn, FCVTZU);
2042 void Assembler::fcvtzs(const Register& rd, const FPRegister& fn) {
2043 FPConvertToInt(rd, fn, FCVTZS);
2047 void Assembler::scvtf(const FPRegister& fd,
2051 Emit(SF(rn) | FPType(fd) | SCVTF | Rn(rn) | Rd(fd));
2053 Emit(SF(rn) | FPType(fd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
2059 void Assembler::ucvtf(const FPRegister& fd,
2063 Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd));
2065 Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
2071 void Assembler::dcptr(Label* label) {
2072 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2073 if (label->is_bound()) {
2074 // The label is bound, so it does not need to be updated and the internal
2075 // reference should be emitted.
2077 // In this case, label->pos() returns the offset of the label from the
2078 // start of the buffer.
2079 internal_reference_positions_.push_back(pc_offset());
2080 dc64(reinterpret_cast<uintptr_t>(buffer_ + label->pos()));
2083 if (label->is_linked()) {
2084 // The label is linked, so the internal reference should be added
2085 // onto the end of the label's link chain.
2087 // In this case, label->pos() returns the offset of the last linked
2088 // instruction from the start of the buffer.
2089 offset = label->pos() - pc_offset();
2090 DCHECK(offset != kStartOfLabelLinkChain);
2092 // The label is unused, so it now becomes linked and the internal
2093 // reference is at the start of the new link chain.
2094 offset = kStartOfLabelLinkChain;
2096 // The instruction at pc is now the last link in the label's chain.
2097 label->link_to(pc_offset());
2099 // Traditionally the offset to the previous instruction in the chain is
2100 // encoded in the instruction payload (e.g. branch range) but internal
2101 // references are not instructions so while unbound they are encoded as
2102 // two consecutive brk instructions. The two 16-bit immediates are used
2103 // to encode the offset.
2104 offset >>= kInstructionSizeLog2;
2105 DCHECK(is_int32(offset));
2106 uint32_t high16 = unsigned_bitextract_32(31, 16, offset);
2107 uint32_t low16 = unsigned_bitextract_32(15, 0, offset);
2116 // Below, a difference in case for the same letter indicates a
2118 // If b is 1, then B is 0.
2119 Instr Assembler::ImmFP32(float imm) {
2120 DCHECK(IsImmFP32(imm));
2121 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000
2122 uint32_t bits = float_to_rawbits(imm);
2124 uint32_t bit7 = ((bits >> 31) & 0x1) << 7;
2126 uint32_t bit6 = ((bits >> 29) & 0x1) << 6;
2127 // bit5_to_0: 00cd.efgh
2128 uint32_t bit5_to_0 = (bits >> 19) & 0x3f;
2130 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
2134 Instr Assembler::ImmFP64(double imm) {
2135 DCHECK(IsImmFP64(imm));
2136 // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2137 // 0000.0000.0000.0000.0000.0000.0000.0000
2138 uint64_t bits = double_to_rawbits(imm);
2140 uint32_t bit7 = ((bits >> 63) & 0x1) << 7;
2142 uint32_t bit6 = ((bits >> 61) & 0x1) << 6;
2143 // bit5_to_0: 00cd.efgh
2144 uint32_t bit5_to_0 = (bits >> 48) & 0x3f;
2146 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
2150 // Code generation helpers.
2151 void Assembler::MoveWide(const Register& rd,
2154 MoveWideImmediateOp mov_op) {
2155 // Ignore the top 32 bits of an immediate if we're moving to a W register.
2156 if (rd.Is32Bits()) {
2157 // Check that the top 32 bits are zero (a positive 32-bit number) or top
2158 // 33 bits are one (a negative 32-bit number, sign extended to 64 bits).
2159 DCHECK(((imm >> kWRegSizeInBits) == 0) ||
2160 ((imm >> (kWRegSizeInBits - 1)) == 0x1ffffffff));
2165 // Explicit shift specified.
2166 DCHECK((shift == 0) || (shift == 16) || (shift == 32) || (shift == 48));
2167 DCHECK(rd.Is64Bits() || (shift == 0) || (shift == 16));
2170 // Calculate a new immediate and shift combination to encode the immediate
2173 if ((imm & ~0xffffUL) == 0) {
2175 } else if ((imm & ~(0xffffUL << 16)) == 0) {
2178 } else if ((imm & ~(0xffffUL << 32)) == 0) {
2179 DCHECK(rd.Is64Bits());
2182 } else if ((imm & ~(0xffffUL << 48)) == 0) {
2183 DCHECK(rd.Is64Bits());
2189 DCHECK(is_uint16(imm));
2191 Emit(SF(rd) | MoveWideImmediateFixed | mov_op |
2192 Rd(rd) | ImmMoveWide(imm) | ShiftMoveWide(shift));
2196 void Assembler::AddSub(const Register& rd,
2198 const Operand& operand,
2201 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2202 DCHECK(!operand.NeedsRelocation(this));
2203 if (operand.IsImmediate()) {
2204 int64_t immediate = operand.ImmediateValue();
2205 DCHECK(IsImmAddSub(immediate));
2206 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
2207 Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) |
2208 ImmAddSub(immediate) | dest_reg | RnSP(rn));
2209 } else if (operand.IsShiftedRegister()) {
2210 DCHECK(operand.reg().SizeInBits() == rd.SizeInBits());
2211 DCHECK(operand.shift() != ROR);
2213 // For instructions of the form:
2214 // add/sub wsp, <Wn>, <Wm> [, LSL #0-3 ]
2215 // add/sub <Wd>, wsp, <Wm> [, LSL #0-3 ]
2216 // add/sub wsp, wsp, <Wm> [, LSL #0-3 ]
2217 // adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ]
2218 // or their 64-bit register equivalents, convert the operand from shifted to
2219 // extended register mode, and emit an add/sub extended instruction.
2220 if (rn.IsSP() || rd.IsSP()) {
2221 DCHECK(!(rd.IsSP() && (S == SetFlags)));
2222 DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S,
2223 AddSubExtendedFixed | op);
2225 DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op);
2228 DCHECK(operand.IsExtendedRegister());
2229 DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op);
2234 void Assembler::AddSubWithCarry(const Register& rd,
2236 const Operand& operand,
2238 AddSubWithCarryOp op) {
2239 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2240 DCHECK(rd.SizeInBits() == operand.reg().SizeInBits());
2241 DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
2242 DCHECK(!operand.NeedsRelocation(this));
2243 Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd));
2247 void Assembler::hlt(int code) {
2248 DCHECK(is_uint16(code));
2249 Emit(HLT | ImmException(code));
2253 void Assembler::brk(int code) {
2254 DCHECK(is_uint16(code));
2255 Emit(BRK | ImmException(code));
2259 void Assembler::EmitStringData(const char* string) {
2260 size_t len = strlen(string) + 1;
2261 DCHECK(RoundUp(len, kInstructionSize) <= static_cast<size_t>(kGap));
2262 EmitData(string, len);
2263 // Pad with NULL characters until pc_ is aligned.
2264 const char pad[] = {'\0', '\0', '\0', '\0'};
2265 STATIC_ASSERT(sizeof(pad) == kInstructionSize);
2266 EmitData(pad, RoundUp(pc_offset(), kInstructionSize) - pc_offset());
2270 void Assembler::debug(const char* message, uint32_t code, Instr params) {
2271 #ifdef USE_SIMULATOR
2272 // Don't generate simulator specific code if we are building a snapshot, which
2273 // might be run on real hardware.
2274 if (!serializer_enabled()) {
2275 // The arguments to the debug marker need to be contiguous in memory, so
2276 // make sure we don't try to emit pools.
2277 BlockPoolsScope scope(this);
2282 // Refer to instructions-arm64.h for a description of the marker and its
2284 hlt(kImmExceptionIsDebug);
2285 DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugCodeOffset);
2287 DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugParamsOffset);
2289 DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugMessageOffset);
2290 EmitStringData(message);
2291 hlt(kImmExceptionIsUnreachable);
2295 // Fall through if Serializer is enabled.
2298 if (params & BREAK) {
2299 hlt(kImmExceptionIsDebug);
2304 void Assembler::Logical(const Register& rd,
2306 const Operand& operand,
2308 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2309 DCHECK(!operand.NeedsRelocation(this));
2310 if (operand.IsImmediate()) {
2311 int64_t immediate = operand.ImmediateValue();
2312 unsigned reg_size = rd.SizeInBits();
2314 DCHECK(immediate != 0);
2315 DCHECK(immediate != -1);
2316 DCHECK(rd.Is64Bits() || is_uint32(immediate));
2318 // If the operation is NOT, invert the operation and immediate.
2319 if ((op & NOT) == NOT) {
2320 op = static_cast<LogicalOp>(op & ~NOT);
2321 immediate = rd.Is64Bits() ? ~immediate : (~immediate & kWRegMask);
2324 unsigned n, imm_s, imm_r;
2325 if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
2326 // Immediate can be encoded in the instruction.
2327 LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
2329 // This case is handled in the macro assembler.
2333 DCHECK(operand.IsShiftedRegister());
2334 DCHECK(operand.reg().SizeInBits() == rd.SizeInBits());
2335 Instr dp_op = static_cast<Instr>(op | LogicalShiftedFixed);
2336 DataProcShiftedRegister(rd, rn, operand, LeaveFlags, dp_op);
2341 void Assembler::LogicalImmediate(const Register& rd,
2347 unsigned reg_size = rd.SizeInBits();
2348 Instr dest_reg = (op == ANDS) ? Rd(rd) : RdSP(rd);
2349 Emit(SF(rd) | LogicalImmediateFixed | op | BitN(n, reg_size) |
2350 ImmSetBits(imm_s, reg_size) | ImmRotate(imm_r, reg_size) | dest_reg |
2355 void Assembler::ConditionalCompare(const Register& rn,
2356 const Operand& operand,
2359 ConditionalCompareOp op) {
2361 DCHECK(!operand.NeedsRelocation(this));
2362 if (operand.IsImmediate()) {
2363 int64_t immediate = operand.ImmediateValue();
2364 DCHECK(IsImmConditionalCompare(immediate));
2365 ccmpop = ConditionalCompareImmediateFixed | op | ImmCondCmp(immediate);
2367 DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
2368 ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg());
2370 Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv));
2374 void Assembler::DataProcessing1Source(const Register& rd,
2376 DataProcessing1SourceOp op) {
2377 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2378 Emit(SF(rn) | op | Rn(rn) | Rd(rd));
2382 void Assembler::FPDataProcessing1Source(const FPRegister& fd,
2383 const FPRegister& fn,
2384 FPDataProcessing1SourceOp op) {
2385 Emit(FPType(fn) | op | Rn(fn) | Rd(fd));
2389 void Assembler::FPDataProcessing2Source(const FPRegister& fd,
2390 const FPRegister& fn,
2391 const FPRegister& fm,
2392 FPDataProcessing2SourceOp op) {
2393 DCHECK(fd.SizeInBits() == fn.SizeInBits());
2394 DCHECK(fd.SizeInBits() == fm.SizeInBits());
2395 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd));
2399 void Assembler::FPDataProcessing3Source(const FPRegister& fd,
2400 const FPRegister& fn,
2401 const FPRegister& fm,
2402 const FPRegister& fa,
2403 FPDataProcessing3SourceOp op) {
2404 DCHECK(AreSameSizeAndType(fd, fn, fm, fa));
2405 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa));
2409 void Assembler::EmitShift(const Register& rd,
2412 unsigned shift_amount) {
2415 lsl(rd, rn, shift_amount);
2418 lsr(rd, rn, shift_amount);
2421 asr(rd, rn, shift_amount);
2424 ror(rd, rn, shift_amount);
2432 void Assembler::EmitExtendShift(const Register& rd,
2435 unsigned left_shift) {
2436 DCHECK(rd.SizeInBits() >= rn.SizeInBits());
2437 unsigned reg_size = rd.SizeInBits();
2438 // Use the correct size of register.
2439 Register rn_ = Register::Create(rn.code(), rd.SizeInBits());
2440 // Bits extracted are high_bit:0.
2441 unsigned high_bit = (8 << (extend & 0x3)) - 1;
2442 // Number of bits left in the result that are not introduced by the shift.
2443 unsigned non_shift_bits = (reg_size - left_shift) & (reg_size - 1);
2445 if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) {
2449 case UXTW: ubfm(rd, rn_, non_shift_bits, high_bit); break;
2452 case SXTW: sbfm(rd, rn_, non_shift_bits, high_bit); break;
2455 DCHECK(rn.SizeInBits() == kXRegSizeInBits);
2456 // Nothing to extend. Just shift.
2457 lsl(rd, rn_, left_shift);
2460 default: UNREACHABLE();
2463 // No need to extend as the extended bits would be shifted away.
2464 lsl(rd, rn_, left_shift);
2469 void Assembler::DataProcShiftedRegister(const Register& rd,
2471 const Operand& operand,
2474 DCHECK(operand.IsShiftedRegister());
2475 DCHECK(rn.Is64Bits() || (rn.Is32Bits() && is_uint5(operand.shift_amount())));
2476 DCHECK(!operand.NeedsRelocation(this));
2477 Emit(SF(rd) | op | Flags(S) |
2478 ShiftDP(operand.shift()) | ImmDPShift(operand.shift_amount()) |
2479 Rm(operand.reg()) | Rn(rn) | Rd(rd));
2483 void Assembler::DataProcExtendedRegister(const Register& rd,
2485 const Operand& operand,
2488 DCHECK(!operand.NeedsRelocation(this));
2489 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
2490 Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) |
2491 ExtendMode(operand.extend()) | ImmExtendShift(operand.shift_amount()) |
2492 dest_reg | RnSP(rn));
2496 bool Assembler::IsImmAddSub(int64_t immediate) {
2497 return is_uint12(immediate) ||
2498 (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0));
2501 void Assembler::LoadStore(const CPURegister& rt,
2502 const MemOperand& addr,
2504 Instr memop = op | Rt(rt) | RnSP(addr.base());
2505 int64_t offset = addr.offset();
2507 if (addr.IsImmediateOffset()) {
2508 LSDataSize size = CalcLSDataSize(op);
2509 if (IsImmLSScaled(offset, size)) {
2510 // Use the scaled addressing mode.
2511 Emit(LoadStoreUnsignedOffsetFixed | memop |
2512 ImmLSUnsigned(offset >> size));
2513 } else if (IsImmLSUnscaled(offset)) {
2514 // Use the unscaled addressing mode.
2515 Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset));
2517 // This case is handled in the macro assembler.
2520 } else if (addr.IsRegisterOffset()) {
2521 Extend ext = addr.extend();
2522 Shift shift = addr.shift();
2523 unsigned shift_amount = addr.shift_amount();
2525 // LSL is encoded in the option field as UXTX.
2530 // Shifts are encoded in one bit, indicating a left shift by the memory
2532 DCHECK((shift_amount == 0) ||
2533 (shift_amount == static_cast<unsigned>(CalcLSDataSize(op))));
2534 Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) |
2535 ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0));
2537 // Pre-index and post-index modes.
2538 DCHECK(!rt.Is(addr.base()));
2539 if (IsImmLSUnscaled(offset)) {
2540 if (addr.IsPreIndex()) {
2541 Emit(LoadStorePreIndexFixed | memop | ImmLS(offset));
2543 DCHECK(addr.IsPostIndex());
2544 Emit(LoadStorePostIndexFixed | memop | ImmLS(offset));
2547 // This case is handled in the macro assembler.
2554 bool Assembler::IsImmLSUnscaled(int64_t offset) {
2555 return is_int9(offset);
2559 bool Assembler::IsImmLSScaled(int64_t offset, LSDataSize size) {
2560 bool offset_is_size_multiple = (((offset >> size) << size) == offset);
2561 return offset_is_size_multiple && is_uint12(offset >> size);
2565 bool Assembler::IsImmLSPair(int64_t offset, LSDataSize size) {
2566 bool offset_is_size_multiple = (((offset >> size) << size) == offset);
2567 return offset_is_size_multiple && is_int7(offset >> size);
2571 // Test if a given value can be encoded in the immediate field of a logical
2573 // If it can be encoded, the function returns true, and values pointed to by n,
2574 // imm_s and imm_r are updated with immediates encoded in the format required
2575 // by the corresponding fields in the logical instruction.
2576 // If it can not be encoded, the function returns false, and the values pointed
2577 // to by n, imm_s and imm_r are undefined.
2578 bool Assembler::IsImmLogical(uint64_t value,
2583 DCHECK((n != NULL) && (imm_s != NULL) && (imm_r != NULL));
2584 DCHECK((width == kWRegSizeInBits) || (width == kXRegSizeInBits));
2586 bool negate = false;
2588 // Logical immediates are encoded using parameters n, imm_s and imm_r using
2589 // the following table:
2591 // N imms immr size S R
2592 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr)
2593 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr)
2594 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr)
2595 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr)
2596 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr)
2597 // 0 11110s xxxxxr 2 UInt(s) UInt(r)
2598 // (s bits must not be all set)
2600 // A pattern is constructed of size bits, where the least significant S+1 bits
2601 // are set. The pattern is rotated right by R, and repeated across a 32 or
2602 // 64-bit value, depending on destination register width.
2604 // Put another way: the basic format of a logical immediate is a single
2605 // contiguous stretch of 1 bits, repeated across the whole word at intervals
2606 // given by a power of 2. To identify them quickly, we first locate the
2607 // lowest stretch of 1 bits, then the next 1 bit above that; that combination
2608 // is different for every logical immediate, so it gives us all the
2609 // information we need to identify the only logical immediate that our input
2610 // could be, and then we simply check if that's the value we actually have.
2612 // (The rotation parameter does give the possibility of the stretch of 1 bits
2613 // going 'round the end' of the word. To deal with that, we observe that in
2614 // any situation where that happens the bitwise NOT of the value is also a
2615 // valid logical immediate. So we simply invert the input whenever its low bit
2616 // is set, and then we know that the rotated case can't arise.)
2619 // If the low bit is 1, negate the value, and set a flag to remember that we
2620 // did (so that we can adjust the return values appropriately).
2625 if (width == kWRegSizeInBits) {
2626 // To handle 32-bit logical immediates, the very easiest thing is to repeat
2627 // the input value twice to make a 64-bit word. The correct encoding of that
2628 // as a logical immediate will also be the correct encoding of the 32-bit
2631 // The most-significant 32 bits may not be zero (ie. negate is true) so
2632 // shift the value left before duplicating it.
2633 value <<= kWRegSizeInBits;
2634 value |= value >> kWRegSizeInBits;
2637 // The basic analysis idea: imagine our input word looks like this.
2639 // 0011111000111110001111100011111000111110001111100011111000111110
2643 // We find the lowest set bit (as an actual power-of-2 value, not its index)
2644 // and call it a. Then we add a to our original number, which wipes out the
2645 // bottommost stretch of set bits and replaces it with a 1 carried into the
2646 // next zero bit. Then we look for the new lowest set bit, which is in
2647 // position b, and subtract it, so now our number is just like the original
2648 // but with the lowest stretch of set bits completely gone. Now we find the
2649 // lowest set bit again, which is position c in the diagram above. Then we'll
2650 // measure the distance d between bit positions a and c (using CLZ), and that
2651 // tells us that the only valid logical immediate that could possibly be equal
2652 // to this number is the one in which a stretch of bits running from a to just
2653 // below b is replicated every d bits.
2654 uint64_t a = LargestPowerOf2Divisor(value);
2655 uint64_t value_plus_a = value + a;
2656 uint64_t b = LargestPowerOf2Divisor(value_plus_a);
2657 uint64_t value_plus_a_minus_b = value_plus_a - b;
2658 uint64_t c = LargestPowerOf2Divisor(value_plus_a_minus_b);
2660 int d, clz_a, out_n;
2664 // The general case, in which there is more than one stretch of set bits.
2665 // Compute the repeat distance d, and set up a bitmask covering the basic
2666 // unit of repetition (i.e. a word with the bottom d bits set). Also, in all
2667 // of these cases the N bit of the output will be zero.
2668 clz_a = CountLeadingZeros(a, kXRegSizeInBits);
2669 int clz_c = CountLeadingZeros(c, kXRegSizeInBits);
2671 mask = ((V8_UINT64_C(1) << d) - 1);
2674 // Handle degenerate cases.
2676 // If any of those 'find lowest set bit' operations didn't find a set bit at
2677 // all, then the word will have been zero thereafter, so in particular the
2678 // last lowest_set_bit operation will have returned zero. So we can test for
2679 // all the special case conditions in one go by seeing if c is zero.
2681 // The input was zero (or all 1 bits, which will come to here too after we
2682 // inverted it at the start of the function), for which we just return
2686 // Otherwise, if c was zero but a was not, then there's just one stretch
2687 // of set bits in our word, meaning that we have the trivial case of
2688 // d == 64 and only one 'repetition'. Set up all the same variables as in
2689 // the general case above, and set the N bit in the output.
2690 clz_a = CountLeadingZeros(a, kXRegSizeInBits);
2692 mask = ~V8_UINT64_C(0);
2697 // If the repeat period d is not a power of two, it can't be encoded.
2698 if (!IS_POWER_OF_TWO(d)) {
2702 if (((b - a) & ~mask) != 0) {
2703 // If the bit stretch (b - a) does not fit within the mask derived from the
2704 // repeat period, then fail.
2708 // The only possible option is b - a repeated every d bits. Now we're going to
2709 // actually construct the valid logical immediate derived from that
2710 // specification, and see if it equals our original input.
2712 // To repeat a value every d bits, we multiply it by a number of the form
2713 // (1 + 2^d + 2^(2d) + ...), i.e. 0x0001000100010001 or similar. These can
2714 // be derived using a table lookup on CLZ(d).
2715 static const uint64_t multipliers[] = {
2716 0x0000000000000001UL,
2717 0x0000000100000001UL,
2718 0x0001000100010001UL,
2719 0x0101010101010101UL,
2720 0x1111111111111111UL,
2721 0x5555555555555555UL,
2723 int multiplier_idx = CountLeadingZeros(d, kXRegSizeInBits) - 57;
2724 // Ensure that the index to the multipliers array is within bounds.
2725 DCHECK((multiplier_idx >= 0) &&
2726 (static_cast<size_t>(multiplier_idx) < arraysize(multipliers)));
2727 uint64_t multiplier = multipliers[multiplier_idx];
2728 uint64_t candidate = (b - a) * multiplier;
2730 if (value != candidate) {
2731 // The candidate pattern doesn't match our input value, so fail.
2735 // We have a match! This is a valid logical immediate, so now we have to
2736 // construct the bits and pieces of the instruction encoding that generates
2739 // Count the set bits in our basic stretch. The special case of clz(0) == -1
2740 // makes the answer come out right for stretches that reach the very top of
2741 // the word (e.g. numbers like 0xffffc00000000000).
2742 int clz_b = (b == 0) ? -1 : CountLeadingZeros(b, kXRegSizeInBits);
2743 int s = clz_a - clz_b;
2745 // Decide how many bits to rotate right by, to put the low bit of that basic
2746 // stretch in position a.
2749 // If we inverted the input right at the start of this function, here's
2750 // where we compensate: the number of set bits becomes the number of clear
2751 // bits, and the rotation count is based on position b rather than position
2752 // a (since b is the location of the 'lowest' 1 bit after inversion).
2754 r = (clz_b + 1) & (d - 1);
2756 r = (clz_a + 1) & (d - 1);
2759 // Now we're done, except for having to encode the S output in such a way that
2760 // it gives both the number of set bits and the length of the repeated
2761 // segment. The s field is encoded like this:
2764 // ssssss 64 UInt(ssssss)
2765 // 0sssss 32 UInt(sssss)
2766 // 10ssss 16 UInt(ssss)
2767 // 110sss 8 UInt(sss)
2768 // 1110ss 4 UInt(ss)
2771 // So we 'or' (-d << 1) with our computed s to form imms.
2773 *imm_s = ((-d << 1) | (s - 1)) & 0x3f;
2780 bool Assembler::IsImmConditionalCompare(int64_t immediate) {
2781 return is_uint5(immediate);
2785 bool Assembler::IsImmFP32(float imm) {
2786 // Valid values will have the form:
2787 // aBbb.bbbc.defg.h000.0000.0000.0000.0000
2788 uint32_t bits = float_to_rawbits(imm);
2789 // bits[19..0] are cleared.
2790 if ((bits & 0x7ffff) != 0) {
2794 // bits[29..25] are all set or all cleared.
2795 uint32_t b_pattern = (bits >> 16) & 0x3e00;
2796 if (b_pattern != 0 && b_pattern != 0x3e00) {
2800 // bit[30] and bit[29] are opposite.
2801 if (((bits ^ (bits << 1)) & 0x40000000) == 0) {
2809 bool Assembler::IsImmFP64(double imm) {
2810 // Valid values will have the form:
2811 // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2812 // 0000.0000.0000.0000.0000.0000.0000.0000
2813 uint64_t bits = double_to_rawbits(imm);
2814 // bits[47..0] are cleared.
2815 if ((bits & 0xffffffffffffL) != 0) {
2819 // bits[61..54] are all set or all cleared.
2820 uint32_t b_pattern = (bits >> 48) & 0x3fc0;
2821 if (b_pattern != 0 && b_pattern != 0x3fc0) {
2825 // bit[62] and bit[61] are opposite.
2826 if (((bits ^ (bits << 1)) & 0x4000000000000000L) == 0) {
2834 void Assembler::GrowBuffer() {
2835 if (!own_buffer_) FATAL("external code buffer is too small");
2837 // Compute new buffer size.
2838 CodeDesc desc; // the new buffer
2839 if (buffer_size_ < 1 * MB) {
2840 desc.buffer_size = 2 * buffer_size_;
2842 desc.buffer_size = buffer_size_ + 1 * MB;
2844 CHECK_GT(desc.buffer_size, 0); // No overflow.
2846 byte* buffer = reinterpret_cast<byte*>(buffer_);
2848 // Set up new buffer.
2849 desc.buffer = NewArray<byte>(desc.buffer_size);
2851 desc.instr_size = pc_offset();
2852 desc.reloc_size = (buffer + buffer_size_) - reloc_info_writer.pos();
2855 intptr_t pc_delta = desc.buffer - buffer;
2856 intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
2857 (buffer + buffer_size_);
2858 memmove(desc.buffer, buffer, desc.instr_size);
2859 memmove(reloc_info_writer.pos() + rc_delta,
2860 reloc_info_writer.pos(), desc.reloc_size);
2863 DeleteArray(buffer_);
2864 buffer_ = desc.buffer;
2865 buffer_size_ = desc.buffer_size;
2866 pc_ = reinterpret_cast<byte*>(pc_) + pc_delta;
2867 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2868 reloc_info_writer.last_pc() + pc_delta);
2870 // None of our relocation types are pc relative pointing outside the code
2871 // buffer nor pc absolute pointing inside the code buffer, so there is no need
2872 // to relocate any emitted relocation entries.
2874 // Relocate internal references.
2875 for (auto pos : internal_reference_positions_) {
2876 intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos);
2880 // Pending relocation entries are also relative, no need to relocate.
2884 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2885 // We do not try to reuse pool constants.
2886 RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL);
2887 if (((rmode >= RelocInfo::JS_RETURN) &&
2888 (rmode <= RelocInfo::DEBUG_BREAK_SLOT)) ||
2889 (rmode == RelocInfo::INTERNAL_REFERENCE) ||
2890 (rmode == RelocInfo::CONST_POOL) ||
2891 (rmode == RelocInfo::VENEER_POOL) ||
2892 (rmode == RelocInfo::DEOPT_REASON)) {
2893 // Adjust code for new modes.
2894 DCHECK(RelocInfo::IsDebugBreakSlot(rmode)
2895 || RelocInfo::IsJSReturn(rmode)
2896 || RelocInfo::IsComment(rmode)
2897 || RelocInfo::IsDeoptReason(rmode)
2898 || RelocInfo::IsPosition(rmode)
2899 || RelocInfo::IsInternalReference(rmode)
2900 || RelocInfo::IsConstPool(rmode)
2901 || RelocInfo::IsVeneerPool(rmode));
2902 // These modes do not need an entry in the constant pool.
2904 constpool_.RecordEntry(data, rmode);
2905 // Make sure the constant pool is not emitted in place of the next
2906 // instruction for which we just recorded relocation info.
2907 BlockConstPoolFor(1);
2910 if (!RelocInfo::IsNone(rmode)) {
2911 // Don't record external references unless the heap will be serialized.
2912 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
2913 !serializer_enabled() && !emit_debug_code()) {
2916 DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
2917 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
2918 RelocInfo reloc_info_with_ast_id(
2919 reinterpret_cast<byte*>(pc_), rmode, RecordedAstId().ToInt(), NULL);
2920 ClearRecordedAstId();
2921 reloc_info_writer.Write(&reloc_info_with_ast_id);
2923 reloc_info_writer.Write(&rinfo);
2929 void Assembler::BlockConstPoolFor(int instructions) {
2930 int pc_limit = pc_offset() + instructions * kInstructionSize;
2931 if (no_const_pool_before_ < pc_limit) {
2932 no_const_pool_before_ = pc_limit;
2933 // Make sure the pool won't be blocked for too long.
2934 DCHECK(pc_limit < constpool_.MaxPcOffset());
2937 if (next_constant_pool_check_ < no_const_pool_before_) {
2938 next_constant_pool_check_ = no_const_pool_before_;
2943 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
2944 // Some short sequence of instruction mustn't be broken up by constant pool
2945 // emission, such sequences are protected by calls to BlockConstPoolFor and
2946 // BlockConstPoolScope.
2947 if (is_const_pool_blocked()) {
2948 // Something is wrong if emission is forced and blocked at the same time.
2949 DCHECK(!force_emit);
2953 // There is nothing to do if there are no pending constant pool entries.
2954 if (constpool_.IsEmpty()) {
2955 // Calculate the offset of the next check.
2956 SetNextConstPoolCheckIn(kCheckConstPoolInterval);
2960 // We emit a constant pool when:
2961 // * requested to do so by parameter force_emit (e.g. after each function).
2962 // * the distance to the first instruction accessing the constant pool is
2963 // kApproxMaxDistToConstPool or more.
2964 // * the number of entries in the pool is kApproxMaxPoolEntryCount or more.
2965 int dist = constpool_.DistanceToFirstUse();
2966 int count = constpool_.EntryCount();
2968 (dist < kApproxMaxDistToConstPool) &&
2969 (count < kApproxMaxPoolEntryCount)) {
2974 // Emit veneers for branches that would go out of range during emission of the
2976 int worst_case_size = constpool_.WorstCaseSize();
2977 CheckVeneerPool(false, require_jump,
2978 kVeneerDistanceMargin + worst_case_size);
2980 // Check that the code buffer is large enough before emitting the constant
2981 // pool (this includes the gap to the relocation information).
2982 int needed_space = worst_case_size + kGap + 1 * kInstructionSize;
2983 while (buffer_space() <= needed_space) {
2989 constpool_.Emit(require_jump);
2990 DCHECK(SizeOfCodeGeneratedSince(&size_check) <=
2991 static_cast<unsigned>(worst_case_size));
2993 // Since a constant pool was just emitted, move the check offset forward by
2994 // the standard interval.
2995 SetNextConstPoolCheckIn(kCheckConstPoolInterval);
2999 bool Assembler::ShouldEmitVeneer(int max_reachable_pc, int margin) {
3000 // Account for the branch around the veneers and the guard.
3001 int protection_offset = 2 * kInstructionSize;
3002 return pc_offset() > max_reachable_pc - margin - protection_offset -
3003 static_cast<int>(unresolved_branches_.size() * kMaxVeneerCodeSize);
3007 void Assembler::RecordVeneerPool(int location_offset, int size) {
3008 RelocInfo rinfo(buffer_ + location_offset,
3009 RelocInfo::VENEER_POOL, static_cast<intptr_t>(size),
3011 reloc_info_writer.Write(&rinfo);
3015 void Assembler::EmitVeneers(bool force_emit, bool need_protection, int margin) {
3016 BlockPoolsScope scope(this);
3017 RecordComment("[ Veneers");
3019 // The exact size of the veneer pool must be recorded (see the comment at the
3020 // declaration site of RecordConstPool()), but computing the number of
3021 // veneers that will be generated is not obvious. So instead we remember the
3022 // current position and will record the size after the pool has been
3026 int veneer_pool_relocinfo_loc = pc_offset();
3029 if (need_protection) {
3035 Label veneer_size_check;
3037 std::multimap<int, FarBranchInfo>::iterator it, it_to_delete;
3039 it = unresolved_branches_.begin();
3040 while (it != unresolved_branches_.end()) {
3041 if (force_emit || ShouldEmitVeneer(it->first, margin)) {
3042 Instruction* branch = InstructionAt(it->second.pc_offset_);
3043 Label* label = it->second.label_;
3046 bind(&veneer_size_check);
3048 // Patch the branch to point to the current position, and emit a branch
3050 Instruction* veneer = reinterpret_cast<Instruction*>(pc_);
3051 RemoveBranchFromLabelLinkChain(branch, label, veneer);
3052 branch->SetImmPCOffsetTarget(veneer);
3055 DCHECK(SizeOfCodeGeneratedSince(&veneer_size_check) <=
3056 static_cast<uint64_t>(kMaxVeneerCodeSize));
3057 veneer_size_check.Unuse();
3060 it_to_delete = it++;
3061 unresolved_branches_.erase(it_to_delete);
3067 // Record the veneer pool size.
3068 int pool_size = SizeOfCodeGeneratedSince(&size_check);
3069 RecordVeneerPool(veneer_pool_relocinfo_loc, pool_size);
3071 if (unresolved_branches_.empty()) {
3072 next_veneer_pool_check_ = kMaxInt;
3074 next_veneer_pool_check_ =
3075 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
3084 void Assembler::CheckVeneerPool(bool force_emit, bool require_jump,
3086 // There is nothing to do if there are no pending veneer pool entries.
3087 if (unresolved_branches_.empty()) {
3088 DCHECK(next_veneer_pool_check_ == kMaxInt);
3092 DCHECK(pc_offset() < unresolved_branches_first_limit());
3094 // Some short sequence of instruction mustn't be broken up by veneer pool
3095 // emission, such sequences are protected by calls to BlockVeneerPoolFor and
3096 // BlockVeneerPoolScope.
3097 if (is_veneer_pool_blocked()) {
3098 DCHECK(!force_emit);
3102 if (!require_jump) {
3103 // Prefer emitting veneers protected by an existing instruction.
3104 margin *= kVeneerNoProtectionFactor;
3106 if (force_emit || ShouldEmitVeneers(margin)) {
3107 EmitVeneers(force_emit, require_jump, margin);
3109 next_veneer_pool_check_ =
3110 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
3115 int Assembler::buffer_space() const {
3116 return reloc_info_writer.pos() - reinterpret_cast<byte*>(pc_);
3120 void Assembler::RecordConstPool(int size) {
3121 // We only need this for debugger support, to correctly compute offsets in the
3123 RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
3127 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
3128 // No out-of-line constant pool support.
3129 DCHECK(!FLAG_enable_ool_constant_pool);
3130 return isolate->factory()->empty_constant_pool_array();
3134 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
3135 // No out-of-line constant pool support.
3136 DCHECK(!FLAG_enable_ool_constant_pool);
3141 void PatchingAssembler::PatchAdrFar(int64_t target_offset) {
3142 // The code at the current instruction should be:
3148 // Verify the expected code.
3149 Instruction* expected_adr = InstructionAt(0);
3150 CHECK(expected_adr->IsAdr() && (expected_adr->ImmPCRel() == 0));
3151 int rd_code = expected_adr->Rd();
3152 for (int i = 0; i < kAdrFarPatchableNNops; ++i) {
3153 CHECK(InstructionAt((i + 1) * kInstructionSize)->IsNop(ADR_FAR_NOP));
3155 Instruction* expected_movz =
3156 InstructionAt((kAdrFarPatchableNInstrs - 1) * kInstructionSize);
3157 CHECK(expected_movz->IsMovz() &&
3158 (expected_movz->ImmMoveWide() == 0) &&
3159 (expected_movz->ShiftMoveWide() == 0));
3160 int scratch_code = expected_movz->Rd();
3162 // Patch to load the correct address.
3163 Register rd = Register::XRegFromCode(rd_code);
3164 Register scratch = Register::XRegFromCode(scratch_code);
3165 // Addresses are only 48 bits.
3166 adr(rd, target_offset & 0xFFFF);
3167 movz(scratch, (target_offset >> 16) & 0xFFFF, 16);
3168 movk(scratch, (target_offset >> 32) & 0xFFFF, 32);
3169 DCHECK((target_offset >> 48) == 0);
3170 add(rd, rd, scratch);
3174 } } // namespace v8::internal
3176 #endif // V8_TARGET_ARCH_ARM64