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) {
48 // Always align csp in cross compiled code - this is safe and ensures that
49 // csp will always be aligned if it is enabled by probing at runtime.
50 if (FLAG_enable_always_align_csp) supported_ |= 1u << ALWAYS_ALIGN_CSP;
53 if (FLAG_enable_always_align_csp &&
54 (cpu.implementer() == base::CPU::NVIDIA || FLAG_debug_code)) {
55 supported_ |= 1u << ALWAYS_ALIGN_CSP;
61 void CpuFeatures::PrintTarget() { }
62 void CpuFeatures::PrintFeatures() { }
65 // -----------------------------------------------------------------------------
66 // CPURegList utilities.
68 CPURegister CPURegList::PopLowestIndex() {
73 int index = CountTrailingZeros(list_, kRegListSizeInBits);
74 DCHECK((1 << index) & list_);
76 return CPURegister::Create(index, size_, type_);
80 CPURegister CPURegList::PopHighestIndex() {
85 int index = CountLeadingZeros(list_, kRegListSizeInBits);
86 index = kRegListSizeInBits - 1 - index;
87 DCHECK((1 << index) & list_);
89 return CPURegister::Create(index, size_, type_);
93 void CPURegList::RemoveCalleeSaved() {
94 if (type() == CPURegister::kRegister) {
95 Remove(GetCalleeSaved(RegisterSizeInBits()));
96 } else if (type() == CPURegister::kFPRegister) {
97 Remove(GetCalleeSavedFP(RegisterSizeInBits()));
99 DCHECK(type() == CPURegister::kNoRegister);
101 // The list must already be empty, so do nothing.
106 CPURegList CPURegList::GetCalleeSaved(unsigned size) {
107 return CPURegList(CPURegister::kRegister, size, 19, 29);
111 CPURegList CPURegList::GetCalleeSavedFP(unsigned size) {
112 return CPURegList(CPURegister::kFPRegister, size, 8, 15);
116 CPURegList CPURegList::GetCallerSaved(unsigned size) {
117 // Registers x0-x18 and lr (x30) are caller-saved.
118 CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18);
124 CPURegList CPURegList::GetCallerSavedFP(unsigned size) {
125 // Registers d0-d7 and d16-d31 are caller-saved.
126 CPURegList list = CPURegList(CPURegister::kFPRegister, size, 0, 7);
127 list.Combine(CPURegList(CPURegister::kFPRegister, size, 16, 31));
132 // This function defines the list of registers which are associated with a
133 // safepoint slot. Safepoint register slots are saved contiguously on the stack.
134 // MacroAssembler::SafepointRegisterStackIndex handles mapping from register
135 // code to index in the safepoint register slots. Any change here can affect
137 CPURegList CPURegList::GetSafepointSavedRegisters() {
138 CPURegList list = CPURegList::GetCalleeSaved();
140 CPURegList(CPURegister::kRegister, kXRegSizeInBits, kJSCallerSaved));
142 // Note that unfortunately we can't use symbolic names for registers and have
143 // to directly use register codes. This is because this function is used to
144 // initialize some static variables and we can't rely on register variables
145 // to be initialized due to static initialization order issues in C++.
147 // Drop ip0 and ip1 (i.e. x16 and x17), as they should not be expected to be
148 // preserved outside of the macro assembler.
152 // Add x18 to the safepoint list, as although it's not in kJSCallerSaved, it
153 // is a caller-saved register according to the procedure call standard.
156 // Drop jssp as the stack pointer doesn't need to be included.
159 // Add the link register (x30) to the safepoint list.
166 // -----------------------------------------------------------------------------
167 // Implementation of RelocInfo
169 const int RelocInfo::kApplyMask = 0;
172 bool RelocInfo::IsCodedSpecially() {
173 // The deserializer needs to know whether a pointer is specially coded. Being
174 // specially coded on ARM64 means that it is a movz/movk sequence. We don't
175 // generate those for relocatable pointers.
180 bool RelocInfo::IsInConstantPool() {
181 Instruction* instr = reinterpret_cast<Instruction*>(pc_);
182 return instr->IsLdrLiteralX();
186 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
187 // Patch the code at the current address with the supplied instructions.
188 Instr* pc = reinterpret_cast<Instr*>(pc_);
189 Instr* instr = reinterpret_cast<Instr*>(instructions);
190 for (int i = 0; i < instruction_count; i++) {
191 *(pc + i) = *(instr + i);
194 // Indicate that code has changed.
195 CpuFeatures::FlushICache(pc_, instruction_count * kInstructionSize);
199 // Patch the code at the current PC with a call to the target address.
200 // Additional guard instructions can be added if required.
201 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
206 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2,
207 Register reg3, Register reg4) {
208 CPURegList regs(reg1, reg2, reg3, reg4);
209 for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
210 Register candidate = Register::FromAllocationIndex(i);
211 if (regs.IncludesAliasOf(candidate)) continue;
219 bool AreAliased(const CPURegister& reg1, const CPURegister& reg2,
220 const CPURegister& reg3, const CPURegister& reg4,
221 const CPURegister& reg5, const CPURegister& reg6,
222 const CPURegister& reg7, const CPURegister& reg8) {
223 int number_of_valid_regs = 0;
224 int number_of_valid_fpregs = 0;
226 RegList unique_regs = 0;
227 RegList unique_fpregs = 0;
229 const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};
231 for (unsigned i = 0; i < arraysize(regs); i++) {
232 if (regs[i].IsRegister()) {
233 number_of_valid_regs++;
234 unique_regs |= regs[i].Bit();
235 } else if (regs[i].IsFPRegister()) {
236 number_of_valid_fpregs++;
237 unique_fpregs |= regs[i].Bit();
239 DCHECK(!regs[i].IsValid());
243 int number_of_unique_regs =
244 CountSetBits(unique_regs, sizeof(unique_regs) * kBitsPerByte);
245 int number_of_unique_fpregs =
246 CountSetBits(unique_fpregs, sizeof(unique_fpregs) * kBitsPerByte);
248 DCHECK(number_of_valid_regs >= number_of_unique_regs);
249 DCHECK(number_of_valid_fpregs >= number_of_unique_fpregs);
251 return (number_of_valid_regs != number_of_unique_regs) ||
252 (number_of_valid_fpregs != number_of_unique_fpregs);
256 bool AreSameSizeAndType(const CPURegister& reg1, const CPURegister& reg2,
257 const CPURegister& reg3, const CPURegister& reg4,
258 const CPURegister& reg5, const CPURegister& reg6,
259 const CPURegister& reg7, const CPURegister& reg8) {
260 DCHECK(reg1.IsValid());
262 match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1);
263 match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1);
264 match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1);
265 match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1);
266 match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1);
267 match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1);
268 match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1);
273 void Immediate::InitializeHandle(Handle<Object> handle) {
274 AllowDeferredHandleDereference using_raw_address;
276 // Verify all Objects referred by code are NOT in new space.
277 Object* obj = *handle;
278 if (obj->IsHeapObject()) {
279 DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
280 value_ = reinterpret_cast<intptr_t>(handle.location());
281 rmode_ = RelocInfo::EMBEDDED_OBJECT;
283 STATIC_ASSERT(sizeof(intptr_t) == sizeof(int64_t));
284 value_ = reinterpret_cast<intptr_t>(obj);
285 rmode_ = RelocInfo::NONE64;
290 bool Operand::NeedsRelocation(const Assembler* assembler) const {
291 RelocInfo::Mode rmode = immediate_.rmode();
293 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
294 return assembler->serializer_enabled();
297 return !RelocInfo::IsNone(rmode);
302 void ConstPool::RecordEntry(intptr_t data,
303 RelocInfo::Mode mode) {
304 DCHECK(mode != RelocInfo::COMMENT &&
305 mode != RelocInfo::POSITION &&
306 mode != RelocInfo::STATEMENT_POSITION &&
307 mode != RelocInfo::CONST_POOL &&
308 mode != RelocInfo::VENEER_POOL &&
309 mode != RelocInfo::CODE_AGE_SEQUENCE);
311 uint64_t raw_data = static_cast<uint64_t>(data);
312 int offset = assm_->pc_offset();
317 std::pair<uint64_t, int> entry = std::make_pair(raw_data, offset);
318 if (CanBeShared(mode)) {
319 shared_entries_.insert(entry);
320 if (shared_entries_.count(entry.first) == 1) {
321 shared_entries_count++;
324 unique_entries_.push_back(entry);
327 if (EntryCount() > Assembler::kApproxMaxPoolEntryCount) {
328 // Request constant pool emission after the next instruction.
329 assm_->SetNextConstPoolCheckIn(1);
334 int ConstPool::DistanceToFirstUse() {
335 DCHECK(first_use_ >= 0);
336 return assm_->pc_offset() - first_use_;
340 int ConstPool::MaxPcOffset() {
341 // There are no pending entries in the pool so we can never get out of
343 if (IsEmpty()) return kMaxInt;
345 // Entries are not necessarily emitted in the order they are added so in the
346 // worst case the first constant pool use will be accessing the last entry.
347 return first_use_ + kMaxLoadLiteralRange - WorstCaseSize();
351 int ConstPool::WorstCaseSize() {
352 if (IsEmpty()) return 0;
354 // Max size prologue:
356 // ldr xzr, #pool_size
359 // All entries are 64-bit for now.
360 return 4 * kInstructionSize + EntryCount() * kPointerSize;
364 int ConstPool::SizeIfEmittedAtCurrentPc(bool require_jump) {
365 if (IsEmpty()) return 0;
368 // b over ;; if require_jump
369 // ldr xzr, #pool_size
371 // nop ;; if not 64-bit aligned
372 int prologue_size = require_jump ? kInstructionSize : 0;
373 prologue_size += 2 * kInstructionSize;
374 prologue_size += IsAligned(assm_->pc_offset() + prologue_size, 8) ?
375 0 : kInstructionSize;
377 // All entries are 64-bit for now.
378 return prologue_size + EntryCount() * kPointerSize;
382 void ConstPool::Emit(bool require_jump) {
383 DCHECK(!assm_->is_const_pool_blocked());
384 // Prevent recursive pool emission and protect from veneer pools.
385 Assembler::BlockPoolsScope block_pools(assm_);
387 int size = SizeIfEmittedAtCurrentPc(require_jump);
389 assm_->bind(&size_check);
391 assm_->RecordConstPool(size);
392 // Emit the constant pool. It is preceded by an optional branch if
393 // require_jump and a header which will:
394 // 1) Encode the size of the constant pool, for use by the disassembler.
395 // 2) Terminate the program, to try to prevent execution from accidentally
396 // flowing into the constant pool.
397 // 3) align the pool entries to 64-bit.
398 // The header is therefore made of up to three arm64 instructions:
399 // ldr xzr, #<size of the constant pool in 32-bit words>
403 // If executed, the header will likely segfault and lr will point to the
404 // instruction following the offending blr.
405 // TODO(all): Make the alignment part less fragile. Currently code is
406 // allocated as a byte array so there are no guarantees the alignment will
407 // be preserved on compaction. Currently it works as allocation seems to be
410 // Emit branch if required
413 assm_->b(&after_pool);
417 assm_->RecordComment("[ Constant Pool");
422 // Emit constant pool entries.
423 // TODO(all): currently each relocated constant is 64 bits, consider adding
424 // support for 32-bit entries.
426 assm_->RecordComment("]");
428 if (after_pool.is_linked()) {
429 assm_->bind(&after_pool);
432 DCHECK(assm_->SizeOfCodeGeneratedSince(&size_check) ==
433 static_cast<unsigned>(size));
437 void ConstPool::Clear() {
438 shared_entries_.clear();
439 shared_entries_count = 0;
440 unique_entries_.clear();
445 bool ConstPool::CanBeShared(RelocInfo::Mode mode) {
446 // Constant pool currently does not support 32-bit entries.
447 DCHECK(mode != RelocInfo::NONE32);
449 return RelocInfo::IsNone(mode) ||
450 (!assm_->serializer_enabled() && (mode >= RelocInfo::CELL));
454 void ConstPool::EmitMarker() {
455 // A constant pool size is expressed in number of 32-bits words.
456 // Currently all entries are 64-bit.
457 // + 1 is for the crash guard.
458 // + 0/1 for alignment.
459 int word_count = EntryCount() * 2 + 1 +
460 (IsAligned(assm_->pc_offset(), 8) ? 0 : 1);
461 assm_->Emit(LDR_x_lit |
462 Assembler::ImmLLiteral(word_count) |
467 MemOperand::PairResult MemOperand::AreConsistentForPair(
468 const MemOperand& operandA,
469 const MemOperand& operandB,
470 int access_size_log2) {
471 DCHECK(access_size_log2 >= 0);
472 DCHECK(access_size_log2 <= 3);
473 // Step one: check that they share the same base, that the mode is Offset
474 // and that the offset is a multiple of access size.
475 if (!operandA.base().Is(operandB.base()) ||
476 (operandA.addrmode() != Offset) ||
477 (operandB.addrmode() != Offset) ||
478 ((operandA.offset() & ((1 << access_size_log2) - 1)) != 0)) {
481 // Step two: check that the offsets are contiguous and that the range
482 // is OK for ldp/stp.
483 if ((operandB.offset() == operandA.offset() + (1 << access_size_log2)) &&
484 is_int7(operandA.offset() >> access_size_log2)) {
487 if ((operandA.offset() == operandB.offset() + (1 << access_size_log2)) &&
488 is_int7(operandB.offset() >> access_size_log2)) {
495 void ConstPool::EmitGuard() {
497 Instruction* instr = reinterpret_cast<Instruction*>(assm_->pc());
498 DCHECK(instr->preceding()->IsLdrLiteralX() &&
499 instr->preceding()->Rt() == xzr.code());
501 assm_->EmitPoolGuard();
505 void ConstPool::EmitEntries() {
506 DCHECK(IsAligned(assm_->pc_offset(), 8));
508 typedef std::multimap<uint64_t, int>::const_iterator SharedEntriesIterator;
509 SharedEntriesIterator value_it;
510 // Iterate through the keys (constant pool values).
511 for (value_it = shared_entries_.begin();
512 value_it != shared_entries_.end();
513 value_it = shared_entries_.upper_bound(value_it->first)) {
514 std::pair<SharedEntriesIterator, SharedEntriesIterator> range;
515 uint64_t data = value_it->first;
516 range = shared_entries_.equal_range(data);
517 SharedEntriesIterator offset_it;
518 // Iterate through the offsets of a given key.
519 for (offset_it = range.first; offset_it != range.second; offset_it++) {
520 Instruction* instr = assm_->InstructionAt(offset_it->second);
522 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0.
523 DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0);
524 instr->SetImmPCOffsetTarget(assm_->pc());
528 shared_entries_.clear();
529 shared_entries_count = 0;
531 // Emit unique entries.
532 std::vector<std::pair<uint64_t, int> >::const_iterator unique_it;
533 for (unique_it = unique_entries_.begin();
534 unique_it != unique_entries_.end();
536 Instruction* instr = assm_->InstructionAt(unique_it->second);
538 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0.
539 DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0);
540 instr->SetImmPCOffsetTarget(assm_->pc());
541 assm_->dc64(unique_it->first);
543 unique_entries_.clear();
549 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
550 : AssemblerBase(isolate, buffer, buffer_size),
552 recorded_ast_id_(TypeFeedbackId::None()),
553 unresolved_branches_(),
554 positions_recorder_(this) {
555 const_pool_blocked_nesting_ = 0;
556 veneer_pool_blocked_nesting_ = 0;
561 Assembler::~Assembler() {
562 DCHECK(constpool_.IsEmpty());
563 DCHECK(const_pool_blocked_nesting_ == 0);
564 DCHECK(veneer_pool_blocked_nesting_ == 0);
568 void Assembler::Reset() {
570 DCHECK((pc_ >= buffer_) && (pc_ < buffer_ + buffer_size_));
571 DCHECK(const_pool_blocked_nesting_ == 0);
572 DCHECK(veneer_pool_blocked_nesting_ == 0);
573 DCHECK(unresolved_branches_.empty());
574 memset(buffer_, 0, pc_ - buffer_);
577 reloc_info_writer.Reposition(reinterpret_cast<byte*>(buffer_ + buffer_size_),
578 reinterpret_cast<byte*>(pc_));
580 next_constant_pool_check_ = 0;
581 next_veneer_pool_check_ = kMaxInt;
582 no_const_pool_before_ = 0;
583 ClearRecordedAstId();
587 void Assembler::GetCode(CodeDesc* desc) {
588 // Emit constant pool if necessary.
589 CheckConstPool(true, false);
590 DCHECK(constpool_.IsEmpty());
592 // Set up code descriptor.
594 desc->buffer = reinterpret_cast<byte*>(buffer_);
595 desc->buffer_size = buffer_size_;
596 desc->instr_size = pc_offset();
597 desc->reloc_size = (reinterpret_cast<byte*>(buffer_) + buffer_size_) -
598 reloc_info_writer.pos();
604 void Assembler::Align(int m) {
605 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
606 while ((pc_offset() & (m - 1)) != 0) {
612 void Assembler::CheckLabelLinkChain(Label const * label) {
614 if (label->is_linked()) {
615 int linkoffset = label->pos();
616 bool end_of_chain = false;
617 while (!end_of_chain) {
618 Instruction * link = InstructionAt(linkoffset);
619 int linkpcoffset = link->ImmPCOffset();
620 int prevlinkoffset = linkoffset + linkpcoffset;
622 end_of_chain = (linkoffset == prevlinkoffset);
623 linkoffset = linkoffset + linkpcoffset;
630 void Assembler::RemoveBranchFromLabelLinkChain(Instruction* branch,
632 Instruction* label_veneer) {
633 DCHECK(label->is_linked());
635 CheckLabelLinkChain(label);
637 Instruction* link = InstructionAt(label->pos());
638 Instruction* prev_link = link;
639 Instruction* next_link;
640 bool end_of_chain = false;
642 while (link != branch && !end_of_chain) {
643 next_link = link->ImmPCOffsetTarget();
644 end_of_chain = (link == next_link);
649 DCHECK(branch == link);
650 next_link = branch->ImmPCOffsetTarget();
652 if (branch == prev_link) {
653 // The branch is the first instruction in the chain.
654 if (branch == next_link) {
655 // It is also the last instruction in the chain, so it is the only branch
656 // currently referring to this label.
659 label->link_to(reinterpret_cast<byte*>(next_link) - buffer_);
662 } else if (branch == next_link) {
663 // The branch is the last (but not also the first) instruction in the chain.
664 prev_link->SetImmPCOffsetTarget(prev_link);
667 // The branch is in the middle of the chain.
668 if (prev_link->IsTargetInImmPCOffsetRange(next_link)) {
669 prev_link->SetImmPCOffsetTarget(next_link);
670 } else if (label_veneer != NULL) {
671 // Use the veneer for all previous links in the chain.
672 prev_link->SetImmPCOffsetTarget(prev_link);
674 end_of_chain = false;
676 while (!end_of_chain) {
677 next_link = link->ImmPCOffsetTarget();
678 end_of_chain = (link == next_link);
679 link->SetImmPCOffsetTarget(label_veneer);
683 // The assert below will fire.
684 // Some other work could be attempted to fix up the chain, but it would be
685 // rather complicated. If we crash here, we may want to consider using an
686 // other mechanism than a chain of branches.
688 // Note that this situation currently should not happen, as we always call
689 // this function with a veneer to the target label.
690 // However this could happen with a MacroAssembler in the following state:
694 // Tbz(label); // First tbz. Pointing to unconditional branch.
696 // Tbz(label); // Second tbz. Pointing to the first tbz.
698 // and this function is called to remove the first tbz from the label link
699 // chain. Since tbz has a range of +-32KB, the second tbz cannot point to
700 // the unconditional branch.
701 CHECK(prev_link->IsTargetInImmPCOffsetRange(next_link));
706 CheckLabelLinkChain(label);
710 void Assembler::bind(Label* label) {
711 // Bind label to the address at pc_. All instructions (most likely branches)
712 // that are linked to this label will be updated to point to the newly-bound
715 DCHECK(!label->is_near_linked());
716 DCHECK(!label->is_bound());
718 DeleteUnresolvedBranchInfoForLabel(label);
720 // If the label is linked, the link chain looks something like this:
722 // |--I----I-------I-------L
723 // |---------------------->| pc_offset
724 // |-------------->| linkoffset = label->pos()
725 // |<------| link->ImmPCOffset()
726 // |------>| prevlinkoffset = linkoffset + link->ImmPCOffset()
728 // On each iteration, the last link is updated and then removed from the
729 // chain until only one remains. At that point, the label is bound.
731 // If the label is not linked, no preparation is required before binding.
732 while (label->is_linked()) {
733 int linkoffset = label->pos();
734 Instruction* link = InstructionAt(linkoffset);
735 int prevlinkoffset = linkoffset + link->ImmPCOffset();
737 CheckLabelLinkChain(label);
739 DCHECK(linkoffset >= 0);
740 DCHECK(linkoffset < pc_offset());
741 DCHECK((linkoffset > prevlinkoffset) ||
742 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain));
743 DCHECK(prevlinkoffset >= 0);
745 // Update the link to point to the label.
746 link->SetImmPCOffsetTarget(reinterpret_cast<Instruction*>(pc_));
748 // Link the label to the previous link in the chain.
749 if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) {
750 // We hit kStartOfLabelLinkChain, so the chain is fully processed.
753 // Update the label for the next iteration.
754 label->link_to(prevlinkoffset);
757 label->bind_to(pc_offset());
759 DCHECK(label->is_bound());
760 DCHECK(!label->is_linked());
764 int Assembler::LinkAndGetByteOffsetTo(Label* label) {
765 DCHECK(sizeof(*pc_) == 1);
766 CheckLabelLinkChain(label);
769 if (label->is_bound()) {
770 // The label is bound, so it does not need to be updated. Referring
771 // instructions must link directly to the label as they will not be
774 // In this case, label->pos() returns the offset of the label from the
775 // start of the buffer.
777 // Note that offset can be zero for self-referential instructions. (This
778 // could be useful for ADR, for example.)
779 offset = label->pos() - pc_offset();
782 if (label->is_linked()) {
783 // The label is linked, so the referring instruction should be added onto
784 // the end of the label's link chain.
786 // In this case, label->pos() returns the offset of the last linked
787 // instruction from the start of the buffer.
788 offset = label->pos() - pc_offset();
789 DCHECK(offset != kStartOfLabelLinkChain);
790 // Note that the offset here needs to be PC-relative only so that the
791 // first instruction in a buffer can link to an unbound label. Otherwise,
792 // the offset would be 0 for this case, and 0 is reserved for
793 // kStartOfLabelLinkChain.
795 // The label is unused, so it now becomes linked and the referring
796 // instruction is at the start of the new link chain.
797 offset = kStartOfLabelLinkChain;
799 // The instruction at pc is now the last link in the label's chain.
800 label->link_to(pc_offset());
807 void Assembler::DeleteUnresolvedBranchInfoForLabelTraverse(Label* label) {
808 DCHECK(label->is_linked());
809 CheckLabelLinkChain(label);
811 int link_offset = label->pos();
813 bool end_of_chain = false;
815 while (!end_of_chain) {
816 Instruction * link = InstructionAt(link_offset);
817 link_pcoffset = link->ImmPCOffset();
819 // ADR instructions are not handled by veneers.
820 if (link->IsImmBranch()) {
821 int max_reachable_pc = InstructionOffset(link) +
822 Instruction::ImmBranchRange(link->BranchType());
823 typedef std::multimap<int, FarBranchInfo>::iterator unresolved_info_it;
824 std::pair<unresolved_info_it, unresolved_info_it> range;
825 range = unresolved_branches_.equal_range(max_reachable_pc);
826 unresolved_info_it it;
827 for (it = range.first; it != range.second; ++it) {
828 if (it->second.pc_offset_ == link_offset) {
829 unresolved_branches_.erase(it);
835 end_of_chain = (link_pcoffset == 0);
836 link_offset = link_offset + link_pcoffset;
841 void Assembler::DeleteUnresolvedBranchInfoForLabel(Label* label) {
842 if (unresolved_branches_.empty()) {
843 DCHECK(next_veneer_pool_check_ == kMaxInt);
847 if (label->is_linked()) {
848 // Branches to this label will be resolved when the label is bound, normally
849 // just after all the associated info has been deleted.
850 DeleteUnresolvedBranchInfoForLabelTraverse(label);
852 if (unresolved_branches_.empty()) {
853 next_veneer_pool_check_ = kMaxInt;
855 next_veneer_pool_check_ =
856 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
861 void Assembler::StartBlockConstPool() {
862 if (const_pool_blocked_nesting_++ == 0) {
863 // Prevent constant pool checks happening by setting the next check to
864 // the biggest possible offset.
865 next_constant_pool_check_ = kMaxInt;
870 void Assembler::EndBlockConstPool() {
871 if (--const_pool_blocked_nesting_ == 0) {
872 // Check the constant pool hasn't been blocked for too long.
873 DCHECK(pc_offset() < constpool_.MaxPcOffset());
875 // * no_const_pool_before_ >= next_constant_pool_check_ and the emission is
877 // * no_const_pool_before_ < next_constant_pool_check_ and the next emit
878 // will trigger a check.
879 next_constant_pool_check_ = no_const_pool_before_;
884 bool Assembler::is_const_pool_blocked() const {
885 return (const_pool_blocked_nesting_ > 0) ||
886 (pc_offset() < no_const_pool_before_);
890 bool Assembler::IsConstantPoolAt(Instruction* instr) {
891 // The constant pool marker is made of two instructions. These instructions
892 // will never be emitted by the JIT, so checking for the first one is enough:
893 // 0: ldr xzr, #<size of pool>
894 bool result = instr->IsLdrLiteralX() && (instr->Rt() == xzr.code());
896 // It is still worth asserting the marker is complete.
898 DCHECK(!result || (instr->following()->IsBranchAndLinkToRegister() &&
899 instr->following()->Rn() == xzr.code()));
905 int Assembler::ConstantPoolSizeAt(Instruction* instr) {
907 // Assembler::debug() embeds constants directly into the instruction stream.
908 // Although this is not a genuine constant pool, treat it like one to avoid
909 // disassembling the constants.
910 if ((instr->Mask(ExceptionMask) == HLT) &&
911 (instr->ImmException() == kImmExceptionIsDebug)) {
912 const char* message =
913 reinterpret_cast<const char*>(
914 instr->InstructionAtOffset(kDebugMessageOffset));
915 int size = kDebugMessageOffset + strlen(message) + 1;
916 return RoundUp(size, kInstructionSize) / kInstructionSize;
918 // Same for printf support, see MacroAssembler::CallPrintf().
919 if ((instr->Mask(ExceptionMask) == HLT) &&
920 (instr->ImmException() == kImmExceptionIsPrintf)) {
921 return kPrintfLength / kInstructionSize;
924 if (IsConstantPoolAt(instr)) {
925 return instr->ImmLLiteral();
932 void Assembler::EmitPoolGuard() {
933 // We must generate only one instruction as this is used in scopes that
934 // control the size of the code generated.
939 void Assembler::StartBlockVeneerPool() {
940 ++veneer_pool_blocked_nesting_;
944 void Assembler::EndBlockVeneerPool() {
945 if (--veneer_pool_blocked_nesting_ == 0) {
946 // Check the veneer pool hasn't been blocked for too long.
947 DCHECK(unresolved_branches_.empty() ||
948 (pc_offset() < unresolved_branches_first_limit()));
953 void Assembler::br(const Register& xn) {
954 positions_recorder()->WriteRecordedPositions();
955 DCHECK(xn.Is64Bits());
960 void Assembler::blr(const Register& xn) {
961 positions_recorder()->WriteRecordedPositions();
962 DCHECK(xn.Is64Bits());
963 // The pattern 'blr xzr' is used as a guard to detect when execution falls
964 // through the constant pool. It should not be emitted.
970 void Assembler::ret(const Register& xn) {
971 positions_recorder()->WriteRecordedPositions();
972 DCHECK(xn.Is64Bits());
977 void Assembler::b(int imm26) {
978 Emit(B | ImmUncondBranch(imm26));
982 void Assembler::b(Label* label) {
983 positions_recorder()->WriteRecordedPositions();
984 b(LinkAndGetInstructionOffsetTo(label));
988 void Assembler::b(int imm19, Condition cond) {
989 Emit(B_cond | ImmCondBranch(imm19) | cond);
993 void Assembler::b(Label* label, Condition cond) {
994 positions_recorder()->WriteRecordedPositions();
995 b(LinkAndGetInstructionOffsetTo(label), cond);
999 void Assembler::bl(int imm26) {
1000 positions_recorder()->WriteRecordedPositions();
1001 Emit(BL | ImmUncondBranch(imm26));
1005 void Assembler::bl(Label* label) {
1006 positions_recorder()->WriteRecordedPositions();
1007 bl(LinkAndGetInstructionOffsetTo(label));
1011 void Assembler::cbz(const Register& rt,
1013 positions_recorder()->WriteRecordedPositions();
1014 Emit(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt));
1018 void Assembler::cbz(const Register& rt,
1020 positions_recorder()->WriteRecordedPositions();
1021 cbz(rt, LinkAndGetInstructionOffsetTo(label));
1025 void Assembler::cbnz(const Register& rt,
1027 positions_recorder()->WriteRecordedPositions();
1028 Emit(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt));
1032 void Assembler::cbnz(const Register& rt,
1034 positions_recorder()->WriteRecordedPositions();
1035 cbnz(rt, LinkAndGetInstructionOffsetTo(label));
1039 void Assembler::tbz(const Register& rt,
1042 positions_recorder()->WriteRecordedPositions();
1043 DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
1044 Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
1048 void Assembler::tbz(const Register& rt,
1051 positions_recorder()->WriteRecordedPositions();
1052 tbz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
1056 void Assembler::tbnz(const Register& rt,
1059 positions_recorder()->WriteRecordedPositions();
1060 DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
1061 Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
1065 void Assembler::tbnz(const Register& rt,
1068 positions_recorder()->WriteRecordedPositions();
1069 tbnz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
1073 void Assembler::adr(const Register& rd, int imm21) {
1074 DCHECK(rd.Is64Bits());
1075 Emit(ADR | ImmPCRelAddress(imm21) | Rd(rd));
1079 void Assembler::adr(const Register& rd, Label* label) {
1080 adr(rd, LinkAndGetByteOffsetTo(label));
1084 void Assembler::add(const Register& rd,
1086 const Operand& operand) {
1087 AddSub(rd, rn, operand, LeaveFlags, ADD);
1091 void Assembler::adds(const Register& rd,
1093 const Operand& operand) {
1094 AddSub(rd, rn, operand, SetFlags, ADD);
1098 void Assembler::cmn(const Register& rn,
1099 const Operand& operand) {
1100 Register zr = AppropriateZeroRegFor(rn);
1101 adds(zr, rn, operand);
1105 void Assembler::sub(const Register& rd,
1107 const Operand& operand) {
1108 AddSub(rd, rn, operand, LeaveFlags, SUB);
1112 void Assembler::subs(const Register& rd,
1114 const Operand& operand) {
1115 AddSub(rd, rn, operand, SetFlags, SUB);
1119 void Assembler::cmp(const Register& rn, const Operand& operand) {
1120 Register zr = AppropriateZeroRegFor(rn);
1121 subs(zr, rn, operand);
1125 void Assembler::neg(const Register& rd, const Operand& operand) {
1126 Register zr = AppropriateZeroRegFor(rd);
1127 sub(rd, zr, operand);
1131 void Assembler::negs(const Register& rd, const Operand& operand) {
1132 Register zr = AppropriateZeroRegFor(rd);
1133 subs(rd, zr, operand);
1137 void Assembler::adc(const Register& rd,
1139 const Operand& operand) {
1140 AddSubWithCarry(rd, rn, operand, LeaveFlags, ADC);
1144 void Assembler::adcs(const Register& rd,
1146 const Operand& operand) {
1147 AddSubWithCarry(rd, rn, operand, SetFlags, ADC);
1151 void Assembler::sbc(const Register& rd,
1153 const Operand& operand) {
1154 AddSubWithCarry(rd, rn, operand, LeaveFlags, SBC);
1158 void Assembler::sbcs(const Register& rd,
1160 const Operand& operand) {
1161 AddSubWithCarry(rd, rn, operand, SetFlags, SBC);
1165 void Assembler::ngc(const Register& rd, const Operand& operand) {
1166 Register zr = AppropriateZeroRegFor(rd);
1167 sbc(rd, zr, operand);
1171 void Assembler::ngcs(const Register& rd, const Operand& operand) {
1172 Register zr = AppropriateZeroRegFor(rd);
1173 sbcs(rd, zr, operand);
1177 // Logical instructions.
1178 void Assembler::and_(const Register& rd,
1180 const Operand& operand) {
1181 Logical(rd, rn, operand, AND);
1185 void Assembler::ands(const Register& rd,
1187 const Operand& operand) {
1188 Logical(rd, rn, operand, ANDS);
1192 void Assembler::tst(const Register& rn,
1193 const Operand& operand) {
1194 ands(AppropriateZeroRegFor(rn), rn, operand);
1198 void Assembler::bic(const Register& rd,
1200 const Operand& operand) {
1201 Logical(rd, rn, operand, BIC);
1205 void Assembler::bics(const Register& rd,
1207 const Operand& operand) {
1208 Logical(rd, rn, operand, BICS);
1212 void Assembler::orr(const Register& rd,
1214 const Operand& operand) {
1215 Logical(rd, rn, operand, ORR);
1219 void Assembler::orn(const Register& rd,
1221 const Operand& operand) {
1222 Logical(rd, rn, operand, ORN);
1226 void Assembler::eor(const Register& rd,
1228 const Operand& operand) {
1229 Logical(rd, rn, operand, EOR);
1233 void Assembler::eon(const Register& rd,
1235 const Operand& operand) {
1236 Logical(rd, rn, operand, EON);
1240 void Assembler::lslv(const Register& rd,
1242 const Register& rm) {
1243 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1244 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1245 Emit(SF(rd) | LSLV | Rm(rm) | Rn(rn) | Rd(rd));
1249 void Assembler::lsrv(const Register& rd,
1251 const Register& rm) {
1252 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1253 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1254 Emit(SF(rd) | LSRV | Rm(rm) | Rn(rn) | Rd(rd));
1258 void Assembler::asrv(const Register& rd,
1260 const Register& rm) {
1261 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1262 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1263 Emit(SF(rd) | ASRV | Rm(rm) | Rn(rn) | Rd(rd));
1267 void Assembler::rorv(const Register& rd,
1269 const Register& rm) {
1270 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1271 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1272 Emit(SF(rd) | RORV | Rm(rm) | Rn(rn) | Rd(rd));
1276 // Bitfield operations.
1277 void Assembler::bfm(const Register& rd,
1281 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1282 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
1283 Emit(SF(rd) | BFM | N |
1284 ImmR(immr, rd.SizeInBits()) |
1285 ImmS(imms, rn.SizeInBits()) |
1290 void Assembler::sbfm(const Register& rd,
1294 DCHECK(rd.Is64Bits() || rn.Is32Bits());
1295 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
1296 Emit(SF(rd) | SBFM | N |
1297 ImmR(immr, rd.SizeInBits()) |
1298 ImmS(imms, rn.SizeInBits()) |
1303 void Assembler::ubfm(const Register& rd,
1307 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1308 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
1309 Emit(SF(rd) | UBFM | N |
1310 ImmR(immr, rd.SizeInBits()) |
1311 ImmS(imms, rn.SizeInBits()) |
1316 void Assembler::extr(const Register& rd,
1320 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1321 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1322 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
1323 Emit(SF(rd) | EXTR | N | Rm(rm) |
1324 ImmS(lsb, rn.SizeInBits()) | Rn(rn) | Rd(rd));
1328 void Assembler::csel(const Register& rd,
1332 ConditionalSelect(rd, rn, rm, cond, CSEL);
1336 void Assembler::csinc(const Register& rd,
1340 ConditionalSelect(rd, rn, rm, cond, CSINC);
1344 void Assembler::csinv(const Register& rd,
1348 ConditionalSelect(rd, rn, rm, cond, CSINV);
1352 void Assembler::csneg(const Register& rd,
1356 ConditionalSelect(rd, rn, rm, cond, CSNEG);
1360 void Assembler::cset(const Register &rd, Condition cond) {
1361 DCHECK((cond != al) && (cond != nv));
1362 Register zr = AppropriateZeroRegFor(rd);
1363 csinc(rd, zr, zr, NegateCondition(cond));
1367 void Assembler::csetm(const Register &rd, Condition cond) {
1368 DCHECK((cond != al) && (cond != nv));
1369 Register zr = AppropriateZeroRegFor(rd);
1370 csinv(rd, zr, zr, NegateCondition(cond));
1374 void Assembler::cinc(const Register &rd, const Register &rn, Condition cond) {
1375 DCHECK((cond != al) && (cond != nv));
1376 csinc(rd, rn, rn, NegateCondition(cond));
1380 void Assembler::cinv(const Register &rd, const Register &rn, Condition cond) {
1381 DCHECK((cond != al) && (cond != nv));
1382 csinv(rd, rn, rn, NegateCondition(cond));
1386 void Assembler::cneg(const Register &rd, const Register &rn, Condition cond) {
1387 DCHECK((cond != al) && (cond != nv));
1388 csneg(rd, rn, rn, NegateCondition(cond));
1392 void Assembler::ConditionalSelect(const Register& rd,
1396 ConditionalSelectOp op) {
1397 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1398 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1399 Emit(SF(rd) | op | Rm(rm) | Cond(cond) | Rn(rn) | Rd(rd));
1403 void Assembler::ccmn(const Register& rn,
1404 const Operand& operand,
1407 ConditionalCompare(rn, operand, nzcv, cond, CCMN);
1411 void Assembler::ccmp(const Register& rn,
1412 const Operand& operand,
1415 ConditionalCompare(rn, operand, nzcv, cond, CCMP);
1419 void Assembler::DataProcessing3Source(const Register& rd,
1423 DataProcessing3SourceOp op) {
1424 Emit(SF(rd) | op | Rm(rm) | Ra(ra) | Rn(rn) | Rd(rd));
1428 void Assembler::mul(const Register& rd,
1430 const Register& rm) {
1431 DCHECK(AreSameSizeAndType(rd, rn, rm));
1432 Register zr = AppropriateZeroRegFor(rn);
1433 DataProcessing3Source(rd, rn, rm, zr, MADD);
1437 void Assembler::madd(const Register& rd,
1440 const Register& ra) {
1441 DCHECK(AreSameSizeAndType(rd, rn, rm, ra));
1442 DataProcessing3Source(rd, rn, rm, ra, MADD);
1446 void Assembler::mneg(const Register& rd,
1448 const Register& rm) {
1449 DCHECK(AreSameSizeAndType(rd, rn, rm));
1450 Register zr = AppropriateZeroRegFor(rn);
1451 DataProcessing3Source(rd, rn, rm, zr, MSUB);
1455 void Assembler::msub(const Register& rd,
1458 const Register& ra) {
1459 DCHECK(AreSameSizeAndType(rd, rn, rm, ra));
1460 DataProcessing3Source(rd, rn, rm, ra, MSUB);
1464 void Assembler::smaddl(const Register& rd,
1467 const Register& ra) {
1468 DCHECK(rd.Is64Bits() && ra.Is64Bits());
1469 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1470 DataProcessing3Source(rd, rn, rm, ra, SMADDL_x);
1474 void Assembler::smsubl(const Register& rd,
1477 const Register& ra) {
1478 DCHECK(rd.Is64Bits() && ra.Is64Bits());
1479 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1480 DataProcessing3Source(rd, rn, rm, ra, SMSUBL_x);
1484 void Assembler::umaddl(const Register& rd,
1487 const Register& ra) {
1488 DCHECK(rd.Is64Bits() && ra.Is64Bits());
1489 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1490 DataProcessing3Source(rd, rn, rm, ra, UMADDL_x);
1494 void Assembler::umsubl(const Register& rd,
1497 const Register& ra) {
1498 DCHECK(rd.Is64Bits() && ra.Is64Bits());
1499 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1500 DataProcessing3Source(rd, rn, rm, ra, UMSUBL_x);
1504 void Assembler::smull(const Register& rd,
1506 const Register& rm) {
1507 DCHECK(rd.Is64Bits());
1508 DCHECK(rn.Is32Bits() && rm.Is32Bits());
1509 DataProcessing3Source(rd, rn, rm, xzr, SMADDL_x);
1513 void Assembler::smulh(const Register& rd,
1515 const Register& rm) {
1516 DCHECK(AreSameSizeAndType(rd, rn, rm));
1517 DataProcessing3Source(rd, rn, rm, xzr, SMULH_x);
1521 void Assembler::sdiv(const Register& rd,
1523 const Register& rm) {
1524 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1525 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1526 Emit(SF(rd) | SDIV | Rm(rm) | Rn(rn) | Rd(rd));
1530 void Assembler::udiv(const Register& rd,
1532 const Register& rm) {
1533 DCHECK(rd.SizeInBits() == rn.SizeInBits());
1534 DCHECK(rd.SizeInBits() == rm.SizeInBits());
1535 Emit(SF(rd) | UDIV | Rm(rm) | Rn(rn) | Rd(rd));
1539 void Assembler::rbit(const Register& rd,
1540 const Register& rn) {
1541 DataProcessing1Source(rd, rn, RBIT);
1545 void Assembler::rev16(const Register& rd,
1546 const Register& rn) {
1547 DataProcessing1Source(rd, rn, REV16);
1551 void Assembler::rev32(const Register& rd,
1552 const Register& rn) {
1553 DCHECK(rd.Is64Bits());
1554 DataProcessing1Source(rd, rn, REV);
1558 void Assembler::rev(const Register& rd,
1559 const Register& rn) {
1560 DataProcessing1Source(rd, rn, rd.Is64Bits() ? REV_x : REV_w);
1564 void Assembler::clz(const Register& rd,
1565 const Register& rn) {
1566 DataProcessing1Source(rd, rn, CLZ);
1570 void Assembler::cls(const Register& rd,
1571 const Register& rn) {
1572 DataProcessing1Source(rd, rn, CLS);
1576 void Assembler::ldp(const CPURegister& rt,
1577 const CPURegister& rt2,
1578 const MemOperand& src) {
1579 LoadStorePair(rt, rt2, src, LoadPairOpFor(rt, rt2));
1583 void Assembler::stp(const CPURegister& rt,
1584 const CPURegister& rt2,
1585 const MemOperand& dst) {
1586 LoadStorePair(rt, rt2, dst, StorePairOpFor(rt, rt2));
1590 void Assembler::ldpsw(const Register& rt,
1591 const Register& rt2,
1592 const MemOperand& src) {
1593 DCHECK(rt.Is64Bits());
1594 LoadStorePair(rt, rt2, src, LDPSW_x);
1598 void Assembler::LoadStorePair(const CPURegister& rt,
1599 const CPURegister& rt2,
1600 const MemOperand& addr,
1601 LoadStorePairOp op) {
1602 // 'rt' and 'rt2' can only be aliased for stores.
1603 DCHECK(((op & LoadStorePairLBit) == 0) || !rt.Is(rt2));
1604 DCHECK(AreSameSizeAndType(rt, rt2));
1606 Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
1607 ImmLSPair(addr.offset(), CalcLSPairDataSize(op));
1610 if (addr.IsImmediateOffset()) {
1611 addrmodeop = LoadStorePairOffsetFixed;
1613 // Pre-index and post-index modes.
1614 DCHECK(!rt.Is(addr.base()));
1615 DCHECK(!rt2.Is(addr.base()));
1616 DCHECK(addr.offset() != 0);
1617 if (addr.IsPreIndex()) {
1618 addrmodeop = LoadStorePairPreIndexFixed;
1620 DCHECK(addr.IsPostIndex());
1621 addrmodeop = LoadStorePairPostIndexFixed;
1624 Emit(addrmodeop | memop);
1628 void Assembler::ldnp(const CPURegister& rt,
1629 const CPURegister& rt2,
1630 const MemOperand& src) {
1631 LoadStorePairNonTemporal(rt, rt2, src,
1632 LoadPairNonTemporalOpFor(rt, rt2));
1636 void Assembler::stnp(const CPURegister& rt,
1637 const CPURegister& rt2,
1638 const MemOperand& dst) {
1639 LoadStorePairNonTemporal(rt, rt2, dst,
1640 StorePairNonTemporalOpFor(rt, rt2));
1644 void Assembler::LoadStorePairNonTemporal(const CPURegister& rt,
1645 const CPURegister& rt2,
1646 const MemOperand& addr,
1647 LoadStorePairNonTemporalOp op) {
1648 DCHECK(!rt.Is(rt2));
1649 DCHECK(AreSameSizeAndType(rt, rt2));
1650 DCHECK(addr.IsImmediateOffset());
1652 LSDataSize size = CalcLSPairDataSize(
1653 static_cast<LoadStorePairOp>(op & LoadStorePairMask));
1654 Emit(op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
1655 ImmLSPair(addr.offset(), size));
1659 // Memory instructions.
1660 void Assembler::ldrb(const Register& rt, const MemOperand& src) {
1661 LoadStore(rt, src, LDRB_w);
1665 void Assembler::strb(const Register& rt, const MemOperand& dst) {
1666 LoadStore(rt, dst, STRB_w);
1670 void Assembler::ldrsb(const Register& rt, const MemOperand& src) {
1671 LoadStore(rt, src, rt.Is64Bits() ? LDRSB_x : LDRSB_w);
1675 void Assembler::ldrh(const Register& rt, const MemOperand& src) {
1676 LoadStore(rt, src, LDRH_w);
1680 void Assembler::strh(const Register& rt, const MemOperand& dst) {
1681 LoadStore(rt, dst, STRH_w);
1685 void Assembler::ldrsh(const Register& rt, const MemOperand& src) {
1686 LoadStore(rt, src, rt.Is64Bits() ? LDRSH_x : LDRSH_w);
1690 void Assembler::ldr(const CPURegister& rt, const MemOperand& src) {
1691 LoadStore(rt, src, LoadOpFor(rt));
1695 void Assembler::str(const CPURegister& rt, const MemOperand& src) {
1696 LoadStore(rt, src, StoreOpFor(rt));
1700 void Assembler::ldrsw(const Register& rt, const MemOperand& src) {
1701 DCHECK(rt.Is64Bits());
1702 LoadStore(rt, src, LDRSW_x);
1706 void Assembler::ldr_pcrel(const CPURegister& rt, int imm19) {
1707 // The pattern 'ldr xzr, #offset' is used to indicate the beginning of a
1708 // constant pool. It should not be emitted.
1709 DCHECK(!rt.IsZero());
1710 Emit(LoadLiteralOpFor(rt) | ImmLLiteral(imm19) | Rt(rt));
1714 void Assembler::ldr(const CPURegister& rt, const Immediate& imm) {
1715 // Currently we only support 64-bit literals.
1716 DCHECK(rt.Is64Bits());
1718 RecordRelocInfo(imm.rmode(), imm.value());
1719 BlockConstPoolFor(1);
1720 // The load will be patched when the constpool is emitted, patching code
1721 // expect a load literal with offset 0.
1726 void Assembler::mov(const Register& rd, const Register& rm) {
1727 // Moves involving the stack pointer are encoded as add immediate with
1728 // second operand of zero. Otherwise, orr with first operand zr is
1730 if (rd.IsSP() || rm.IsSP()) {
1733 orr(rd, AppropriateZeroRegFor(rd), rm);
1738 void Assembler::mvn(const Register& rd, const Operand& operand) {
1739 orn(rd, AppropriateZeroRegFor(rd), operand);
1743 void Assembler::mrs(const Register& rt, SystemRegister sysreg) {
1744 DCHECK(rt.Is64Bits());
1745 Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt));
1749 void Assembler::msr(SystemRegister sysreg, const Register& rt) {
1750 DCHECK(rt.Is64Bits());
1751 Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg));
1755 void Assembler::hint(SystemHint code) {
1756 Emit(HINT | ImmHint(code) | Rt(xzr));
1760 void Assembler::dmb(BarrierDomain domain, BarrierType type) {
1761 Emit(DMB | ImmBarrierDomain(domain) | ImmBarrierType(type));
1765 void Assembler::dsb(BarrierDomain domain, BarrierType type) {
1766 Emit(DSB | ImmBarrierDomain(domain) | ImmBarrierType(type));
1770 void Assembler::isb() {
1771 Emit(ISB | ImmBarrierDomain(FullSystem) | ImmBarrierType(BarrierAll));
1775 void Assembler::fmov(FPRegister fd, double imm) {
1776 DCHECK(fd.Is64Bits());
1777 DCHECK(IsImmFP64(imm));
1778 Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm));
1782 void Assembler::fmov(FPRegister fd, float imm) {
1783 DCHECK(fd.Is32Bits());
1784 DCHECK(IsImmFP32(imm));
1785 Emit(FMOV_s_imm | Rd(fd) | ImmFP32(imm));
1789 void Assembler::fmov(Register rd, FPRegister fn) {
1790 DCHECK(rd.SizeInBits() == fn.SizeInBits());
1791 FPIntegerConvertOp op = rd.Is32Bits() ? FMOV_ws : FMOV_xd;
1792 Emit(op | Rd(rd) | Rn(fn));
1796 void Assembler::fmov(FPRegister fd, Register rn) {
1797 DCHECK(fd.SizeInBits() == rn.SizeInBits());
1798 FPIntegerConvertOp op = fd.Is32Bits() ? FMOV_sw : FMOV_dx;
1799 Emit(op | Rd(fd) | Rn(rn));
1803 void Assembler::fmov(FPRegister fd, FPRegister fn) {
1804 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1805 Emit(FPType(fd) | FMOV | Rd(fd) | Rn(fn));
1809 void Assembler::fadd(const FPRegister& fd,
1810 const FPRegister& fn,
1811 const FPRegister& fm) {
1812 FPDataProcessing2Source(fd, fn, fm, FADD);
1816 void Assembler::fsub(const FPRegister& fd,
1817 const FPRegister& fn,
1818 const FPRegister& fm) {
1819 FPDataProcessing2Source(fd, fn, fm, FSUB);
1823 void Assembler::fmul(const FPRegister& fd,
1824 const FPRegister& fn,
1825 const FPRegister& fm) {
1826 FPDataProcessing2Source(fd, fn, fm, FMUL);
1830 void Assembler::fmadd(const FPRegister& fd,
1831 const FPRegister& fn,
1832 const FPRegister& fm,
1833 const FPRegister& fa) {
1834 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMADD_s : FMADD_d);
1838 void Assembler::fmsub(const FPRegister& fd,
1839 const FPRegister& fn,
1840 const FPRegister& fm,
1841 const FPRegister& fa) {
1842 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMSUB_s : FMSUB_d);
1846 void Assembler::fnmadd(const FPRegister& fd,
1847 const FPRegister& fn,
1848 const FPRegister& fm,
1849 const FPRegister& fa) {
1850 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMADD_s : FNMADD_d);
1854 void Assembler::fnmsub(const FPRegister& fd,
1855 const FPRegister& fn,
1856 const FPRegister& fm,
1857 const FPRegister& fa) {
1858 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMSUB_s : FNMSUB_d);
1862 void Assembler::fdiv(const FPRegister& fd,
1863 const FPRegister& fn,
1864 const FPRegister& fm) {
1865 FPDataProcessing2Source(fd, fn, fm, FDIV);
1869 void Assembler::fmax(const FPRegister& fd,
1870 const FPRegister& fn,
1871 const FPRegister& fm) {
1872 FPDataProcessing2Source(fd, fn, fm, FMAX);
1876 void Assembler::fmaxnm(const FPRegister& fd,
1877 const FPRegister& fn,
1878 const FPRegister& fm) {
1879 FPDataProcessing2Source(fd, fn, fm, FMAXNM);
1883 void Assembler::fmin(const FPRegister& fd,
1884 const FPRegister& fn,
1885 const FPRegister& fm) {
1886 FPDataProcessing2Source(fd, fn, fm, FMIN);
1890 void Assembler::fminnm(const FPRegister& fd,
1891 const FPRegister& fn,
1892 const FPRegister& fm) {
1893 FPDataProcessing2Source(fd, fn, fm, FMINNM);
1897 void Assembler::fabs(const FPRegister& fd,
1898 const FPRegister& fn) {
1899 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1900 FPDataProcessing1Source(fd, fn, FABS);
1904 void Assembler::fneg(const FPRegister& fd,
1905 const FPRegister& fn) {
1906 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1907 FPDataProcessing1Source(fd, fn, FNEG);
1911 void Assembler::fsqrt(const FPRegister& fd,
1912 const FPRegister& fn) {
1913 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1914 FPDataProcessing1Source(fd, fn, FSQRT);
1918 void Assembler::frinta(const FPRegister& fd,
1919 const FPRegister& fn) {
1920 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1921 FPDataProcessing1Source(fd, fn, FRINTA);
1925 void Assembler::frintm(const FPRegister& fd,
1926 const FPRegister& fn) {
1927 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1928 FPDataProcessing1Source(fd, fn, FRINTM);
1932 void Assembler::frintn(const FPRegister& fd,
1933 const FPRegister& fn) {
1934 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1935 FPDataProcessing1Source(fd, fn, FRINTN);
1939 void Assembler::frintp(const FPRegister& fd, const FPRegister& fn) {
1940 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1941 FPDataProcessing1Source(fd, fn, FRINTP);
1945 void Assembler::frintz(const FPRegister& fd,
1946 const FPRegister& fn) {
1947 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1948 FPDataProcessing1Source(fd, fn, FRINTZ);
1952 void Assembler::fcmp(const FPRegister& fn,
1953 const FPRegister& fm) {
1954 DCHECK(fn.SizeInBits() == fm.SizeInBits());
1955 Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn));
1959 void Assembler::fcmp(const FPRegister& fn,
1962 // Although the fcmp instruction can strictly only take an immediate value of
1963 // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't
1964 // affect the result of the comparison.
1965 DCHECK(value == 0.0);
1966 Emit(FPType(fn) | FCMP_zero | Rn(fn));
1970 void Assembler::fccmp(const FPRegister& fn,
1971 const FPRegister& fm,
1974 DCHECK(fn.SizeInBits() == fm.SizeInBits());
1975 Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv));
1979 void Assembler::fcsel(const FPRegister& fd,
1980 const FPRegister& fn,
1981 const FPRegister& fm,
1983 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1984 DCHECK(fd.SizeInBits() == fm.SizeInBits());
1985 Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd));
1989 void Assembler::FPConvertToInt(const Register& rd,
1990 const FPRegister& fn,
1991 FPIntegerConvertOp op) {
1992 Emit(SF(rd) | FPType(fn) | op | Rn(fn) | Rd(rd));
1996 void Assembler::fcvt(const FPRegister& fd,
1997 const FPRegister& fn) {
1998 if (fd.Is64Bits()) {
1999 // Convert float to double.
2000 DCHECK(fn.Is32Bits());
2001 FPDataProcessing1Source(fd, fn, FCVT_ds);
2003 // Convert double to float.
2004 DCHECK(fn.Is64Bits());
2005 FPDataProcessing1Source(fd, fn, FCVT_sd);
2010 void Assembler::fcvtau(const Register& rd, const FPRegister& fn) {
2011 FPConvertToInt(rd, fn, FCVTAU);
2015 void Assembler::fcvtas(const Register& rd, const FPRegister& fn) {
2016 FPConvertToInt(rd, fn, FCVTAS);
2020 void Assembler::fcvtmu(const Register& rd, const FPRegister& fn) {
2021 FPConvertToInt(rd, fn, FCVTMU);
2025 void Assembler::fcvtms(const Register& rd, const FPRegister& fn) {
2026 FPConvertToInt(rd, fn, FCVTMS);
2030 void Assembler::fcvtnu(const Register& rd, const FPRegister& fn) {
2031 FPConvertToInt(rd, fn, FCVTNU);
2035 void Assembler::fcvtns(const Register& rd, const FPRegister& fn) {
2036 FPConvertToInt(rd, fn, FCVTNS);
2040 void Assembler::fcvtzu(const Register& rd, const FPRegister& fn) {
2041 FPConvertToInt(rd, fn, FCVTZU);
2045 void Assembler::fcvtzs(const Register& rd, const FPRegister& fn) {
2046 FPConvertToInt(rd, fn, FCVTZS);
2050 void Assembler::scvtf(const FPRegister& fd,
2054 Emit(SF(rn) | FPType(fd) | SCVTF | Rn(rn) | Rd(fd));
2056 Emit(SF(rn) | FPType(fd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
2062 void Assembler::ucvtf(const FPRegister& fd,
2066 Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd));
2068 Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
2075 // Below, a difference in case for the same letter indicates a
2077 // If b is 1, then B is 0.
2078 Instr Assembler::ImmFP32(float imm) {
2079 DCHECK(IsImmFP32(imm));
2080 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000
2081 uint32_t bits = float_to_rawbits(imm);
2083 uint32_t bit7 = ((bits >> 31) & 0x1) << 7;
2085 uint32_t bit6 = ((bits >> 29) & 0x1) << 6;
2086 // bit5_to_0: 00cd.efgh
2087 uint32_t bit5_to_0 = (bits >> 19) & 0x3f;
2089 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
2093 Instr Assembler::ImmFP64(double imm) {
2094 DCHECK(IsImmFP64(imm));
2095 // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2096 // 0000.0000.0000.0000.0000.0000.0000.0000
2097 uint64_t bits = double_to_rawbits(imm);
2099 uint32_t bit7 = ((bits >> 63) & 0x1) << 7;
2101 uint32_t bit6 = ((bits >> 61) & 0x1) << 6;
2102 // bit5_to_0: 00cd.efgh
2103 uint32_t bit5_to_0 = (bits >> 48) & 0x3f;
2105 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
2109 // Code generation helpers.
2110 void Assembler::MoveWide(const Register& rd,
2113 MoveWideImmediateOp mov_op) {
2114 // Ignore the top 32 bits of an immediate if we're moving to a W register.
2115 if (rd.Is32Bits()) {
2116 // Check that the top 32 bits are zero (a positive 32-bit number) or top
2117 // 33 bits are one (a negative 32-bit number, sign extended to 64 bits).
2118 DCHECK(((imm >> kWRegSizeInBits) == 0) ||
2119 ((imm >> (kWRegSizeInBits - 1)) == 0x1ffffffff));
2124 // Explicit shift specified.
2125 DCHECK((shift == 0) || (shift == 16) || (shift == 32) || (shift == 48));
2126 DCHECK(rd.Is64Bits() || (shift == 0) || (shift == 16));
2129 // Calculate a new immediate and shift combination to encode the immediate
2132 if ((imm & ~0xffffUL) == 0) {
2134 } else if ((imm & ~(0xffffUL << 16)) == 0) {
2137 } else if ((imm & ~(0xffffUL << 32)) == 0) {
2138 DCHECK(rd.Is64Bits());
2141 } else if ((imm & ~(0xffffUL << 48)) == 0) {
2142 DCHECK(rd.Is64Bits());
2148 DCHECK(is_uint16(imm));
2150 Emit(SF(rd) | MoveWideImmediateFixed | mov_op |
2151 Rd(rd) | ImmMoveWide(imm) | ShiftMoveWide(shift));
2155 void Assembler::AddSub(const Register& rd,
2157 const Operand& operand,
2160 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2161 DCHECK(!operand.NeedsRelocation(this));
2162 if (operand.IsImmediate()) {
2163 int64_t immediate = operand.ImmediateValue();
2164 DCHECK(IsImmAddSub(immediate));
2165 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
2166 Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) |
2167 ImmAddSub(immediate) | dest_reg | RnSP(rn));
2168 } else if (operand.IsShiftedRegister()) {
2169 DCHECK(operand.reg().SizeInBits() == rd.SizeInBits());
2170 DCHECK(operand.shift() != ROR);
2172 // For instructions of the form:
2173 // add/sub wsp, <Wn>, <Wm> [, LSL #0-3 ]
2174 // add/sub <Wd>, wsp, <Wm> [, LSL #0-3 ]
2175 // add/sub wsp, wsp, <Wm> [, LSL #0-3 ]
2176 // adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ]
2177 // or their 64-bit register equivalents, convert the operand from shifted to
2178 // extended register mode, and emit an add/sub extended instruction.
2179 if (rn.IsSP() || rd.IsSP()) {
2180 DCHECK(!(rd.IsSP() && (S == SetFlags)));
2181 DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S,
2182 AddSubExtendedFixed | op);
2184 DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op);
2187 DCHECK(operand.IsExtendedRegister());
2188 DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op);
2193 void Assembler::AddSubWithCarry(const Register& rd,
2195 const Operand& operand,
2197 AddSubWithCarryOp op) {
2198 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2199 DCHECK(rd.SizeInBits() == operand.reg().SizeInBits());
2200 DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
2201 DCHECK(!operand.NeedsRelocation(this));
2202 Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd));
2206 void Assembler::hlt(int code) {
2207 DCHECK(is_uint16(code));
2208 Emit(HLT | ImmException(code));
2212 void Assembler::brk(int code) {
2213 DCHECK(is_uint16(code));
2214 Emit(BRK | ImmException(code));
2218 void Assembler::EmitStringData(const char* string) {
2219 size_t len = strlen(string) + 1;
2220 DCHECK(RoundUp(len, kInstructionSize) <= static_cast<size_t>(kGap));
2221 EmitData(string, len);
2222 // Pad with NULL characters until pc_ is aligned.
2223 const char pad[] = {'\0', '\0', '\0', '\0'};
2224 STATIC_ASSERT(sizeof(pad) == kInstructionSize);
2225 EmitData(pad, RoundUp(pc_offset(), kInstructionSize) - pc_offset());
2229 void Assembler::debug(const char* message, uint32_t code, Instr params) {
2230 #ifdef USE_SIMULATOR
2231 // Don't generate simulator specific code if we are building a snapshot, which
2232 // might be run on real hardware.
2233 if (!serializer_enabled()) {
2234 // The arguments to the debug marker need to be contiguous in memory, so
2235 // make sure we don't try to emit pools.
2236 BlockPoolsScope scope(this);
2241 // Refer to instructions-arm64.h for a description of the marker and its
2243 hlt(kImmExceptionIsDebug);
2244 DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugCodeOffset);
2246 DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugParamsOffset);
2248 DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugMessageOffset);
2249 EmitStringData(message);
2250 hlt(kImmExceptionIsUnreachable);
2254 // Fall through if Serializer is enabled.
2257 if (params & BREAK) {
2258 hlt(kImmExceptionIsDebug);
2263 void Assembler::Logical(const Register& rd,
2265 const Operand& operand,
2267 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2268 DCHECK(!operand.NeedsRelocation(this));
2269 if (operand.IsImmediate()) {
2270 int64_t immediate = operand.ImmediateValue();
2271 unsigned reg_size = rd.SizeInBits();
2273 DCHECK(immediate != 0);
2274 DCHECK(immediate != -1);
2275 DCHECK(rd.Is64Bits() || is_uint32(immediate));
2277 // If the operation is NOT, invert the operation and immediate.
2278 if ((op & NOT) == NOT) {
2279 op = static_cast<LogicalOp>(op & ~NOT);
2280 immediate = rd.Is64Bits() ? ~immediate : (~immediate & kWRegMask);
2283 unsigned n, imm_s, imm_r;
2284 if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
2285 // Immediate can be encoded in the instruction.
2286 LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
2288 // This case is handled in the macro assembler.
2292 DCHECK(operand.IsShiftedRegister());
2293 DCHECK(operand.reg().SizeInBits() == rd.SizeInBits());
2294 Instr dp_op = static_cast<Instr>(op | LogicalShiftedFixed);
2295 DataProcShiftedRegister(rd, rn, operand, LeaveFlags, dp_op);
2300 void Assembler::LogicalImmediate(const Register& rd,
2306 unsigned reg_size = rd.SizeInBits();
2307 Instr dest_reg = (op == ANDS) ? Rd(rd) : RdSP(rd);
2308 Emit(SF(rd) | LogicalImmediateFixed | op | BitN(n, reg_size) |
2309 ImmSetBits(imm_s, reg_size) | ImmRotate(imm_r, reg_size) | dest_reg |
2314 void Assembler::ConditionalCompare(const Register& rn,
2315 const Operand& operand,
2318 ConditionalCompareOp op) {
2320 DCHECK(!operand.NeedsRelocation(this));
2321 if (operand.IsImmediate()) {
2322 int64_t immediate = operand.ImmediateValue();
2323 DCHECK(IsImmConditionalCompare(immediate));
2324 ccmpop = ConditionalCompareImmediateFixed | op | ImmCondCmp(immediate);
2326 DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
2327 ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg());
2329 Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv));
2333 void Assembler::DataProcessing1Source(const Register& rd,
2335 DataProcessing1SourceOp op) {
2336 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2337 Emit(SF(rn) | op | Rn(rn) | Rd(rd));
2341 void Assembler::FPDataProcessing1Source(const FPRegister& fd,
2342 const FPRegister& fn,
2343 FPDataProcessing1SourceOp op) {
2344 Emit(FPType(fn) | op | Rn(fn) | Rd(fd));
2348 void Assembler::FPDataProcessing2Source(const FPRegister& fd,
2349 const FPRegister& fn,
2350 const FPRegister& fm,
2351 FPDataProcessing2SourceOp op) {
2352 DCHECK(fd.SizeInBits() == fn.SizeInBits());
2353 DCHECK(fd.SizeInBits() == fm.SizeInBits());
2354 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd));
2358 void Assembler::FPDataProcessing3Source(const FPRegister& fd,
2359 const FPRegister& fn,
2360 const FPRegister& fm,
2361 const FPRegister& fa,
2362 FPDataProcessing3SourceOp op) {
2363 DCHECK(AreSameSizeAndType(fd, fn, fm, fa));
2364 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa));
2368 void Assembler::EmitShift(const Register& rd,
2371 unsigned shift_amount) {
2374 lsl(rd, rn, shift_amount);
2377 lsr(rd, rn, shift_amount);
2380 asr(rd, rn, shift_amount);
2383 ror(rd, rn, shift_amount);
2391 void Assembler::EmitExtendShift(const Register& rd,
2394 unsigned left_shift) {
2395 DCHECK(rd.SizeInBits() >= rn.SizeInBits());
2396 unsigned reg_size = rd.SizeInBits();
2397 // Use the correct size of register.
2398 Register rn_ = Register::Create(rn.code(), rd.SizeInBits());
2399 // Bits extracted are high_bit:0.
2400 unsigned high_bit = (8 << (extend & 0x3)) - 1;
2401 // Number of bits left in the result that are not introduced by the shift.
2402 unsigned non_shift_bits = (reg_size - left_shift) & (reg_size - 1);
2404 if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) {
2408 case UXTW: ubfm(rd, rn_, non_shift_bits, high_bit); break;
2411 case SXTW: sbfm(rd, rn_, non_shift_bits, high_bit); break;
2414 DCHECK(rn.SizeInBits() == kXRegSizeInBits);
2415 // Nothing to extend. Just shift.
2416 lsl(rd, rn_, left_shift);
2419 default: UNREACHABLE();
2422 // No need to extend as the extended bits would be shifted away.
2423 lsl(rd, rn_, left_shift);
2428 void Assembler::DataProcShiftedRegister(const Register& rd,
2430 const Operand& operand,
2433 DCHECK(operand.IsShiftedRegister());
2434 DCHECK(rn.Is64Bits() || (rn.Is32Bits() && is_uint5(operand.shift_amount())));
2435 DCHECK(!operand.NeedsRelocation(this));
2436 Emit(SF(rd) | op | Flags(S) |
2437 ShiftDP(operand.shift()) | ImmDPShift(operand.shift_amount()) |
2438 Rm(operand.reg()) | Rn(rn) | Rd(rd));
2442 void Assembler::DataProcExtendedRegister(const Register& rd,
2444 const Operand& operand,
2447 DCHECK(!operand.NeedsRelocation(this));
2448 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
2449 Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) |
2450 ExtendMode(operand.extend()) | ImmExtendShift(operand.shift_amount()) |
2451 dest_reg | RnSP(rn));
2455 bool Assembler::IsImmAddSub(int64_t immediate) {
2456 return is_uint12(immediate) ||
2457 (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0));
2460 void Assembler::LoadStore(const CPURegister& rt,
2461 const MemOperand& addr,
2463 Instr memop = op | Rt(rt) | RnSP(addr.base());
2464 int64_t offset = addr.offset();
2466 if (addr.IsImmediateOffset()) {
2467 LSDataSize size = CalcLSDataSize(op);
2468 if (IsImmLSScaled(offset, size)) {
2469 // Use the scaled addressing mode.
2470 Emit(LoadStoreUnsignedOffsetFixed | memop |
2471 ImmLSUnsigned(offset >> size));
2472 } else if (IsImmLSUnscaled(offset)) {
2473 // Use the unscaled addressing mode.
2474 Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset));
2476 // This case is handled in the macro assembler.
2479 } else if (addr.IsRegisterOffset()) {
2480 Extend ext = addr.extend();
2481 Shift shift = addr.shift();
2482 unsigned shift_amount = addr.shift_amount();
2484 // LSL is encoded in the option field as UXTX.
2489 // Shifts are encoded in one bit, indicating a left shift by the memory
2491 DCHECK((shift_amount == 0) ||
2492 (shift_amount == static_cast<unsigned>(CalcLSDataSize(op))));
2493 Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) |
2494 ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0));
2496 // Pre-index and post-index modes.
2497 DCHECK(!rt.Is(addr.base()));
2498 if (IsImmLSUnscaled(offset)) {
2499 if (addr.IsPreIndex()) {
2500 Emit(LoadStorePreIndexFixed | memop | ImmLS(offset));
2502 DCHECK(addr.IsPostIndex());
2503 Emit(LoadStorePostIndexFixed | memop | ImmLS(offset));
2506 // This case is handled in the macro assembler.
2513 bool Assembler::IsImmLSUnscaled(int64_t offset) {
2514 return is_int9(offset);
2518 bool Assembler::IsImmLSScaled(int64_t offset, LSDataSize size) {
2519 bool offset_is_size_multiple = (((offset >> size) << size) == offset);
2520 return offset_is_size_multiple && is_uint12(offset >> size);
2524 bool Assembler::IsImmLSPair(int64_t offset, LSDataSize size) {
2525 bool offset_is_size_multiple = (((offset >> size) << size) == offset);
2526 return offset_is_size_multiple && is_int7(offset >> size);
2530 // Test if a given value can be encoded in the immediate field of a logical
2532 // If it can be encoded, the function returns true, and values pointed to by n,
2533 // imm_s and imm_r are updated with immediates encoded in the format required
2534 // by the corresponding fields in the logical instruction.
2535 // If it can not be encoded, the function returns false, and the values pointed
2536 // to by n, imm_s and imm_r are undefined.
2537 bool Assembler::IsImmLogical(uint64_t value,
2542 DCHECK((n != NULL) && (imm_s != NULL) && (imm_r != NULL));
2543 DCHECK((width == kWRegSizeInBits) || (width == kXRegSizeInBits));
2545 bool negate = false;
2547 // Logical immediates are encoded using parameters n, imm_s and imm_r using
2548 // the following table:
2550 // N imms immr size S R
2551 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr)
2552 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr)
2553 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr)
2554 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr)
2555 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr)
2556 // 0 11110s xxxxxr 2 UInt(s) UInt(r)
2557 // (s bits must not be all set)
2559 // A pattern is constructed of size bits, where the least significant S+1 bits
2560 // are set. The pattern is rotated right by R, and repeated across a 32 or
2561 // 64-bit value, depending on destination register width.
2563 // Put another way: the basic format of a logical immediate is a single
2564 // contiguous stretch of 1 bits, repeated across the whole word at intervals
2565 // given by a power of 2. To identify them quickly, we first locate the
2566 // lowest stretch of 1 bits, then the next 1 bit above that; that combination
2567 // is different for every logical immediate, so it gives us all the
2568 // information we need to identify the only logical immediate that our input
2569 // could be, and then we simply check if that's the value we actually have.
2571 // (The rotation parameter does give the possibility of the stretch of 1 bits
2572 // going 'round the end' of the word. To deal with that, we observe that in
2573 // any situation where that happens the bitwise NOT of the value is also a
2574 // valid logical immediate. So we simply invert the input whenever its low bit
2575 // is set, and then we know that the rotated case can't arise.)
2578 // If the low bit is 1, negate the value, and set a flag to remember that we
2579 // did (so that we can adjust the return values appropriately).
2584 if (width == kWRegSizeInBits) {
2585 // To handle 32-bit logical immediates, the very easiest thing is to repeat
2586 // the input value twice to make a 64-bit word. The correct encoding of that
2587 // as a logical immediate will also be the correct encoding of the 32-bit
2590 // The most-significant 32 bits may not be zero (ie. negate is true) so
2591 // shift the value left before duplicating it.
2592 value <<= kWRegSizeInBits;
2593 value |= value >> kWRegSizeInBits;
2596 // The basic analysis idea: imagine our input word looks like this.
2598 // 0011111000111110001111100011111000111110001111100011111000111110
2602 // We find the lowest set bit (as an actual power-of-2 value, not its index)
2603 // and call it a. Then we add a to our original number, which wipes out the
2604 // bottommost stretch of set bits and replaces it with a 1 carried into the
2605 // next zero bit. Then we look for the new lowest set bit, which is in
2606 // position b, and subtract it, so now our number is just like the original
2607 // but with the lowest stretch of set bits completely gone. Now we find the
2608 // lowest set bit again, which is position c in the diagram above. Then we'll
2609 // measure the distance d between bit positions a and c (using CLZ), and that
2610 // tells us that the only valid logical immediate that could possibly be equal
2611 // to this number is the one in which a stretch of bits running from a to just
2612 // below b is replicated every d bits.
2613 uint64_t a = LargestPowerOf2Divisor(value);
2614 uint64_t value_plus_a = value + a;
2615 uint64_t b = LargestPowerOf2Divisor(value_plus_a);
2616 uint64_t value_plus_a_minus_b = value_plus_a - b;
2617 uint64_t c = LargestPowerOf2Divisor(value_plus_a_minus_b);
2619 int d, clz_a, out_n;
2623 // The general case, in which there is more than one stretch of set bits.
2624 // Compute the repeat distance d, and set up a bitmask covering the basic
2625 // unit of repetition (i.e. a word with the bottom d bits set). Also, in all
2626 // of these cases the N bit of the output will be zero.
2627 clz_a = CountLeadingZeros(a, kXRegSizeInBits);
2628 int clz_c = CountLeadingZeros(c, kXRegSizeInBits);
2630 mask = ((V8_UINT64_C(1) << d) - 1);
2633 // Handle degenerate cases.
2635 // If any of those 'find lowest set bit' operations didn't find a set bit at
2636 // all, then the word will have been zero thereafter, so in particular the
2637 // last lowest_set_bit operation will have returned zero. So we can test for
2638 // all the special case conditions in one go by seeing if c is zero.
2640 // The input was zero (or all 1 bits, which will come to here too after we
2641 // inverted it at the start of the function), for which we just return
2645 // Otherwise, if c was zero but a was not, then there's just one stretch
2646 // of set bits in our word, meaning that we have the trivial case of
2647 // d == 64 and only one 'repetition'. Set up all the same variables as in
2648 // the general case above, and set the N bit in the output.
2649 clz_a = CountLeadingZeros(a, kXRegSizeInBits);
2651 mask = ~V8_UINT64_C(0);
2656 // If the repeat period d is not a power of two, it can't be encoded.
2657 if (!IS_POWER_OF_TWO(d)) {
2661 if (((b - a) & ~mask) != 0) {
2662 // If the bit stretch (b - a) does not fit within the mask derived from the
2663 // repeat period, then fail.
2667 // The only possible option is b - a repeated every d bits. Now we're going to
2668 // actually construct the valid logical immediate derived from that
2669 // specification, and see if it equals our original input.
2671 // To repeat a value every d bits, we multiply it by a number of the form
2672 // (1 + 2^d + 2^(2d) + ...), i.e. 0x0001000100010001 or similar. These can
2673 // be derived using a table lookup on CLZ(d).
2674 static const uint64_t multipliers[] = {
2675 0x0000000000000001UL,
2676 0x0000000100000001UL,
2677 0x0001000100010001UL,
2678 0x0101010101010101UL,
2679 0x1111111111111111UL,
2680 0x5555555555555555UL,
2682 int multiplier_idx = CountLeadingZeros(d, kXRegSizeInBits) - 57;
2683 // Ensure that the index to the multipliers array is within bounds.
2684 DCHECK((multiplier_idx >= 0) &&
2685 (static_cast<size_t>(multiplier_idx) < arraysize(multipliers)));
2686 uint64_t multiplier = multipliers[multiplier_idx];
2687 uint64_t candidate = (b - a) * multiplier;
2689 if (value != candidate) {
2690 // The candidate pattern doesn't match our input value, so fail.
2694 // We have a match! This is a valid logical immediate, so now we have to
2695 // construct the bits and pieces of the instruction encoding that generates
2698 // Count the set bits in our basic stretch. The special case of clz(0) == -1
2699 // makes the answer come out right for stretches that reach the very top of
2700 // the word (e.g. numbers like 0xffffc00000000000).
2701 int clz_b = (b == 0) ? -1 : CountLeadingZeros(b, kXRegSizeInBits);
2702 int s = clz_a - clz_b;
2704 // Decide how many bits to rotate right by, to put the low bit of that basic
2705 // stretch in position a.
2708 // If we inverted the input right at the start of this function, here's
2709 // where we compensate: the number of set bits becomes the number of clear
2710 // bits, and the rotation count is based on position b rather than position
2711 // a (since b is the location of the 'lowest' 1 bit after inversion).
2713 r = (clz_b + 1) & (d - 1);
2715 r = (clz_a + 1) & (d - 1);
2718 // Now we're done, except for having to encode the S output in such a way that
2719 // it gives both the number of set bits and the length of the repeated
2720 // segment. The s field is encoded like this:
2723 // ssssss 64 UInt(ssssss)
2724 // 0sssss 32 UInt(sssss)
2725 // 10ssss 16 UInt(ssss)
2726 // 110sss 8 UInt(sss)
2727 // 1110ss 4 UInt(ss)
2730 // So we 'or' (-d << 1) with our computed s to form imms.
2732 *imm_s = ((-d << 1) | (s - 1)) & 0x3f;
2739 bool Assembler::IsImmConditionalCompare(int64_t immediate) {
2740 return is_uint5(immediate);
2744 bool Assembler::IsImmFP32(float imm) {
2745 // Valid values will have the form:
2746 // aBbb.bbbc.defg.h000.0000.0000.0000.0000
2747 uint32_t bits = float_to_rawbits(imm);
2748 // bits[19..0] are cleared.
2749 if ((bits & 0x7ffff) != 0) {
2753 // bits[29..25] are all set or all cleared.
2754 uint32_t b_pattern = (bits >> 16) & 0x3e00;
2755 if (b_pattern != 0 && b_pattern != 0x3e00) {
2759 // bit[30] and bit[29] are opposite.
2760 if (((bits ^ (bits << 1)) & 0x40000000) == 0) {
2768 bool Assembler::IsImmFP64(double imm) {
2769 // Valid values will have the form:
2770 // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2771 // 0000.0000.0000.0000.0000.0000.0000.0000
2772 uint64_t bits = double_to_rawbits(imm);
2773 // bits[47..0] are cleared.
2774 if ((bits & 0xffffffffffffL) != 0) {
2778 // bits[61..54] are all set or all cleared.
2779 uint32_t b_pattern = (bits >> 48) & 0x3fc0;
2780 if (b_pattern != 0 && b_pattern != 0x3fc0) {
2784 // bit[62] and bit[61] are opposite.
2785 if (((bits ^ (bits << 1)) & 0x4000000000000000L) == 0) {
2793 void Assembler::GrowBuffer() {
2794 if (!own_buffer_) FATAL("external code buffer is too small");
2796 // Compute new buffer size.
2797 CodeDesc desc; // the new buffer
2798 if (buffer_size_ < 1 * MB) {
2799 desc.buffer_size = 2 * buffer_size_;
2801 desc.buffer_size = buffer_size_ + 1 * MB;
2803 CHECK_GT(desc.buffer_size, 0); // No overflow.
2805 byte* buffer = reinterpret_cast<byte*>(buffer_);
2807 // Set up new buffer.
2808 desc.buffer = NewArray<byte>(desc.buffer_size);
2810 desc.instr_size = pc_offset();
2811 desc.reloc_size = (buffer + buffer_size_) - reloc_info_writer.pos();
2814 intptr_t pc_delta = desc.buffer - buffer;
2815 intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
2816 (buffer + buffer_size_);
2817 memmove(desc.buffer, buffer, desc.instr_size);
2818 memmove(reloc_info_writer.pos() + rc_delta,
2819 reloc_info_writer.pos(), desc.reloc_size);
2822 DeleteArray(buffer_);
2823 buffer_ = desc.buffer;
2824 buffer_size_ = desc.buffer_size;
2825 pc_ = reinterpret_cast<byte*>(pc_) + pc_delta;
2826 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2827 reloc_info_writer.last_pc() + pc_delta);
2829 // None of our relocation types are pc relative pointing outside the code
2830 // buffer nor pc absolute pointing inside the code buffer, so there is no need
2831 // to relocate any emitted relocation entries.
2833 // Pending relocation entries are also relative, no need to relocate.
2837 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2838 // We do not try to reuse pool constants.
2839 RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL);
2840 if (((rmode >= RelocInfo::JS_RETURN) &&
2841 (rmode <= RelocInfo::DEBUG_BREAK_SLOT)) ||
2842 (rmode == RelocInfo::CONST_POOL) ||
2843 (rmode == RelocInfo::VENEER_POOL)) {
2844 // Adjust code for new modes.
2845 DCHECK(RelocInfo::IsDebugBreakSlot(rmode)
2846 || RelocInfo::IsJSReturn(rmode)
2847 || RelocInfo::IsComment(rmode)
2848 || RelocInfo::IsPosition(rmode)
2849 || RelocInfo::IsConstPool(rmode)
2850 || RelocInfo::IsVeneerPool(rmode));
2851 // These modes do not need an entry in the constant pool.
2853 constpool_.RecordEntry(data, rmode);
2854 // Make sure the constant pool is not emitted in place of the next
2855 // instruction for which we just recorded relocation info.
2856 BlockConstPoolFor(1);
2859 if (!RelocInfo::IsNone(rmode)) {
2860 // Don't record external references unless the heap will be serialized.
2861 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
2862 !serializer_enabled() && !emit_debug_code()) {
2865 DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
2866 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
2867 RelocInfo reloc_info_with_ast_id(
2868 reinterpret_cast<byte*>(pc_), rmode, RecordedAstId().ToInt(), NULL);
2869 ClearRecordedAstId();
2870 reloc_info_writer.Write(&reloc_info_with_ast_id);
2872 reloc_info_writer.Write(&rinfo);
2878 void Assembler::BlockConstPoolFor(int instructions) {
2879 int pc_limit = pc_offset() + instructions * kInstructionSize;
2880 if (no_const_pool_before_ < pc_limit) {
2881 no_const_pool_before_ = pc_limit;
2882 // Make sure the pool won't be blocked for too long.
2883 DCHECK(pc_limit < constpool_.MaxPcOffset());
2886 if (next_constant_pool_check_ < no_const_pool_before_) {
2887 next_constant_pool_check_ = no_const_pool_before_;
2892 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
2893 // Some short sequence of instruction mustn't be broken up by constant pool
2894 // emission, such sequences are protected by calls to BlockConstPoolFor and
2895 // BlockConstPoolScope.
2896 if (is_const_pool_blocked()) {
2897 // Something is wrong if emission is forced and blocked at the same time.
2898 DCHECK(!force_emit);
2902 // There is nothing to do if there are no pending constant pool entries.
2903 if (constpool_.IsEmpty()) {
2904 // Calculate the offset of the next check.
2905 SetNextConstPoolCheckIn(kCheckConstPoolInterval);
2909 // We emit a constant pool when:
2910 // * requested to do so by parameter force_emit (e.g. after each function).
2911 // * the distance to the first instruction accessing the constant pool is
2912 // kApproxMaxDistToConstPool or more.
2913 // * the number of entries in the pool is kApproxMaxPoolEntryCount or more.
2914 int dist = constpool_.DistanceToFirstUse();
2915 int count = constpool_.EntryCount();
2917 (dist < kApproxMaxDistToConstPool) &&
2918 (count < kApproxMaxPoolEntryCount)) {
2923 // Emit veneers for branches that would go out of range during emission of the
2925 int worst_case_size = constpool_.WorstCaseSize();
2926 CheckVeneerPool(false, require_jump,
2927 kVeneerDistanceMargin + worst_case_size);
2929 // Check that the code buffer is large enough before emitting the constant
2930 // pool (this includes the gap to the relocation information).
2931 int needed_space = worst_case_size + kGap + 1 * kInstructionSize;
2932 while (buffer_space() <= needed_space) {
2938 constpool_.Emit(require_jump);
2939 DCHECK(SizeOfCodeGeneratedSince(&size_check) <=
2940 static_cast<unsigned>(worst_case_size));
2942 // Since a constant pool was just emitted, move the check offset forward by
2943 // the standard interval.
2944 SetNextConstPoolCheckIn(kCheckConstPoolInterval);
2948 bool Assembler::ShouldEmitVeneer(int max_reachable_pc, int margin) {
2949 // Account for the branch around the veneers and the guard.
2950 int protection_offset = 2 * kInstructionSize;
2951 return pc_offset() > max_reachable_pc - margin - protection_offset -
2952 static_cast<int>(unresolved_branches_.size() * kMaxVeneerCodeSize);
2956 void Assembler::RecordVeneerPool(int location_offset, int size) {
2957 RelocInfo rinfo(buffer_ + location_offset,
2958 RelocInfo::VENEER_POOL, static_cast<intptr_t>(size),
2960 reloc_info_writer.Write(&rinfo);
2964 void Assembler::EmitVeneers(bool force_emit, bool need_protection, int margin) {
2965 BlockPoolsScope scope(this);
2966 RecordComment("[ Veneers");
2968 // The exact size of the veneer pool must be recorded (see the comment at the
2969 // declaration site of RecordConstPool()), but computing the number of
2970 // veneers that will be generated is not obvious. So instead we remember the
2971 // current position and will record the size after the pool has been
2975 int veneer_pool_relocinfo_loc = pc_offset();
2978 if (need_protection) {
2984 Label veneer_size_check;
2986 std::multimap<int, FarBranchInfo>::iterator it, it_to_delete;
2988 it = unresolved_branches_.begin();
2989 while (it != unresolved_branches_.end()) {
2990 if (force_emit || ShouldEmitVeneer(it->first, margin)) {
2991 Instruction* branch = InstructionAt(it->second.pc_offset_);
2992 Label* label = it->second.label_;
2995 bind(&veneer_size_check);
2997 // Patch the branch to point to the current position, and emit a branch
2999 Instruction* veneer = reinterpret_cast<Instruction*>(pc_);
3000 RemoveBranchFromLabelLinkChain(branch, label, veneer);
3001 branch->SetImmPCOffsetTarget(veneer);
3004 DCHECK(SizeOfCodeGeneratedSince(&veneer_size_check) <=
3005 static_cast<uint64_t>(kMaxVeneerCodeSize));
3006 veneer_size_check.Unuse();
3009 it_to_delete = it++;
3010 unresolved_branches_.erase(it_to_delete);
3016 // Record the veneer pool size.
3017 int pool_size = SizeOfCodeGeneratedSince(&size_check);
3018 RecordVeneerPool(veneer_pool_relocinfo_loc, pool_size);
3020 if (unresolved_branches_.empty()) {
3021 next_veneer_pool_check_ = kMaxInt;
3023 next_veneer_pool_check_ =
3024 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
3033 void Assembler::CheckVeneerPool(bool force_emit, bool require_jump,
3035 // There is nothing to do if there are no pending veneer pool entries.
3036 if (unresolved_branches_.empty()) {
3037 DCHECK(next_veneer_pool_check_ == kMaxInt);
3041 DCHECK(pc_offset() < unresolved_branches_first_limit());
3043 // Some short sequence of instruction mustn't be broken up by veneer pool
3044 // emission, such sequences are protected by calls to BlockVeneerPoolFor and
3045 // BlockVeneerPoolScope.
3046 if (is_veneer_pool_blocked()) {
3047 DCHECK(!force_emit);
3051 if (!require_jump) {
3052 // Prefer emitting veneers protected by an existing instruction.
3053 margin *= kVeneerNoProtectionFactor;
3055 if (force_emit || ShouldEmitVeneers(margin)) {
3056 EmitVeneers(force_emit, require_jump, margin);
3058 next_veneer_pool_check_ =
3059 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
3064 void Assembler::RecordComment(const char* msg) {
3065 if (FLAG_code_comments) {
3067 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
3072 int Assembler::buffer_space() const {
3073 return reloc_info_writer.pos() - reinterpret_cast<byte*>(pc_);
3077 void Assembler::RecordJSReturn() {
3078 positions_recorder()->WriteRecordedPositions();
3080 RecordRelocInfo(RelocInfo::JS_RETURN);
3084 void Assembler::RecordDebugBreakSlot() {
3085 positions_recorder()->WriteRecordedPositions();
3087 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
3091 void Assembler::RecordConstPool(int size) {
3092 // We only need this for debugger support, to correctly compute offsets in the
3094 RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
3098 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
3099 // No out-of-line constant pool support.
3100 DCHECK(!FLAG_enable_ool_constant_pool);
3101 return isolate->factory()->empty_constant_pool_array();
3105 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
3106 // No out-of-line constant pool support.
3107 DCHECK(!FLAG_enable_ool_constant_pool);
3112 void PatchingAssembler::PatchAdrFar(int64_t target_offset) {
3113 // The code at the current instruction should be:
3119 // Verify the expected code.
3120 Instruction* expected_adr = InstructionAt(0);
3121 CHECK(expected_adr->IsAdr() && (expected_adr->ImmPCRel() == 0));
3122 int rd_code = expected_adr->Rd();
3123 for (int i = 0; i < kAdrFarPatchableNNops; ++i) {
3124 CHECK(InstructionAt((i + 1) * kInstructionSize)->IsNop(ADR_FAR_NOP));
3126 Instruction* expected_movz =
3127 InstructionAt((kAdrFarPatchableNInstrs - 1) * kInstructionSize);
3128 CHECK(expected_movz->IsMovz() &&
3129 (expected_movz->ImmMoveWide() == 0) &&
3130 (expected_movz->ShiftMoveWide() == 0));
3131 int scratch_code = expected_movz->Rd();
3133 // Patch to load the correct address.
3134 Register rd = Register::XRegFromCode(rd_code);
3135 Register scratch = Register::XRegFromCode(scratch_code);
3136 // Addresses are only 48 bits.
3137 adr(rd, target_offset & 0xFFFF);
3138 movz(scratch, (target_offset >> 16) & 0xFFFF, 16);
3139 movk(scratch, (target_offset >> 32) & 0xFFFF, 32);
3140 DCHECK((target_offset >> 48) == 0);
3141 add(rd, rd, scratch);
3145 } } // namespace v8::internal
3147 #endif // V8_TARGET_ARCH_ARM64