1 // Copyright 2013 the V8 project authors. All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
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.
16 //
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.
28 
29 #include "src/v8.h"
30 
31 #if V8_TARGET_ARCH_ARM64
32 
33 #define ARM64_DEFINE_REG_STATICS
34 
35 #include "src/arm64/assembler-arm64-inl.h"
36 #include "src/base/bits.h"
37 #include "src/base/cpu.h"
38 
39 namespace v8 {
40 namespace internal {
41 
42 
43 // -----------------------------------------------------------------------------
44 // CpuFeatures implementation.
45 
ProbeImpl(bool cross_compile)46 void CpuFeatures::ProbeImpl(bool cross_compile) {
47   if (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;
51   } else {
52     base::CPU cpu;
53     if (FLAG_enable_always_align_csp &&
54         (cpu.implementer() == base::CPU::NVIDIA || FLAG_debug_code)) {
55       supported_ |= 1u << ALWAYS_ALIGN_CSP;
56     }
57   }
58 }
59 
60 
PrintTarget()61 void CpuFeatures::PrintTarget() { }
PrintFeatures()62 void CpuFeatures::PrintFeatures() { }
63 
64 
65 // -----------------------------------------------------------------------------
66 // CPURegList utilities.
67 
PopLowestIndex()68 CPURegister CPURegList::PopLowestIndex() {
69   DCHECK(IsValid());
70   if (IsEmpty()) {
71     return NoCPUReg;
72   }
73   int index = CountTrailingZeros(list_, kRegListSizeInBits);
74   DCHECK((1 << index) & list_);
75   Remove(index);
76   return CPURegister::Create(index, size_, type_);
77 }
78 
79 
PopHighestIndex()80 CPURegister CPURegList::PopHighestIndex() {
81   DCHECK(IsValid());
82   if (IsEmpty()) {
83     return NoCPUReg;
84   }
85   int index = CountLeadingZeros(list_, kRegListSizeInBits);
86   index = kRegListSizeInBits - 1 - index;
87   DCHECK((1 << index) & list_);
88   Remove(index);
89   return CPURegister::Create(index, size_, type_);
90 }
91 
92 
RemoveCalleeSaved()93 void CPURegList::RemoveCalleeSaved() {
94   if (type() == CPURegister::kRegister) {
95     Remove(GetCalleeSaved(RegisterSizeInBits()));
96   } else if (type() == CPURegister::kFPRegister) {
97     Remove(GetCalleeSavedFP(RegisterSizeInBits()));
98   } else {
99     DCHECK(type() == CPURegister::kNoRegister);
100     DCHECK(IsEmpty());
101     // The list must already be empty, so do nothing.
102   }
103 }
104 
105 
GetCalleeSaved(unsigned size)106 CPURegList CPURegList::GetCalleeSaved(unsigned size) {
107   return CPURegList(CPURegister::kRegister, size, 19, 29);
108 }
109 
110 
GetCalleeSavedFP(unsigned size)111 CPURegList CPURegList::GetCalleeSavedFP(unsigned size) {
112   return CPURegList(CPURegister::kFPRegister, size, 8, 15);
113 }
114 
115 
GetCallerSaved(unsigned size)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);
119   list.Combine(lr);
120   return list;
121 }
122 
123 
GetCallerSavedFP(unsigned size)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));
128   return list;
129 }
130 
131 
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
136 // this mapping.
GetSafepointSavedRegisters()137 CPURegList CPURegList::GetSafepointSavedRegisters() {
138   CPURegList list = CPURegList::GetCalleeSaved();
139   list.Combine(
140       CPURegList(CPURegister::kRegister, kXRegSizeInBits, kJSCallerSaved));
141 
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++.
146 
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.
149   list.Remove(16);
150   list.Remove(17);
151 
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.
154   list.Combine(18);
155 
156   // Drop jssp as the stack pointer doesn't need to be included.
157   list.Remove(28);
158 
159   // Add the link register (x30) to the safepoint list.
160   list.Combine(30);
161 
162   return list;
163 }
164 
165 
166 // -----------------------------------------------------------------------------
167 // Implementation of RelocInfo
168 
169 const int RelocInfo::kApplyMask = 0;
170 
171 
IsCodedSpecially()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.
176   return false;
177 }
178 
179 
IsInConstantPool()180 bool RelocInfo::IsInConstantPool() {
181   Instruction* instr = reinterpret_cast<Instruction*>(pc_);
182   return instr->IsLdrLiteralX();
183 }
184 
185 
PatchCode(byte * instructions,int instruction_count)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);
192   }
193 
194   // Indicate that code has changed.
195   CpuFeatures::FlushICache(pc_, instruction_count * kInstructionSize);
196 }
197 
198 
199 // Patch the code at the current PC with a call to the target address.
200 // Additional guard instructions can be added if required.
PatchCodeWithCall(Address target,int guard_bytes)201 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
202   UNIMPLEMENTED();
203 }
204 
205 
GetAllocatableRegisterThatIsNotOneOf(Register reg1,Register reg2,Register reg3,Register reg4)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;
212     return candidate;
213   }
214   UNREACHABLE();
215   return NoReg;
216 }
217 
218 
AreAliased(const CPURegister & reg1,const CPURegister & reg2,const CPURegister & reg3,const CPURegister & reg4,const CPURegister & reg5,const CPURegister & reg6,const CPURegister & reg7,const CPURegister & reg8)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;
225 
226   RegList unique_regs = 0;
227   RegList unique_fpregs = 0;
228 
229   const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};
230 
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();
238     } else {
239       DCHECK(!regs[i].IsValid());
240     }
241   }
242 
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);
247 
248   DCHECK(number_of_valid_regs >= number_of_unique_regs);
249   DCHECK(number_of_valid_fpregs >= number_of_unique_fpregs);
250 
251   return (number_of_valid_regs != number_of_unique_regs) ||
252          (number_of_valid_fpregs != number_of_unique_fpregs);
253 }
254 
255 
AreSameSizeAndType(const CPURegister & reg1,const CPURegister & reg2,const CPURegister & reg3,const CPURegister & reg4,const CPURegister & reg5,const CPURegister & reg6,const CPURegister & reg7,const CPURegister & reg8)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());
261   bool match = true;
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);
269   return match;
270 }
271 
272 
InitializeHandle(Handle<Object> handle)273 void Immediate::InitializeHandle(Handle<Object> handle) {
274   AllowDeferredHandleDereference using_raw_address;
275 
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;
282   } else {
283     STATIC_ASSERT(sizeof(intptr_t) == sizeof(int64_t));
284     value_ = reinterpret_cast<intptr_t>(obj);
285     rmode_ = RelocInfo::NONE64;
286   }
287 }
288 
289 
NeedsRelocation(const Assembler * assembler) const290 bool Operand::NeedsRelocation(const Assembler* assembler) const {
291   RelocInfo::Mode rmode = immediate_.rmode();
292 
293   if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
294     return assembler->serializer_enabled();
295   }
296 
297   return !RelocInfo::IsNone(rmode);
298 }
299 
300 
301 // Constant Pool.
RecordEntry(intptr_t data,RelocInfo::Mode mode)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);
310 
311   uint64_t raw_data = static_cast<uint64_t>(data);
312   int offset = assm_->pc_offset();
313   if (IsEmpty()) {
314     first_use_ = offset;
315   }
316 
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++;
322     }
323   } else {
324     unique_entries_.push_back(entry);
325   }
326 
327   if (EntryCount() > Assembler::kApproxMaxPoolEntryCount) {
328     // Request constant pool emission after the next instruction.
329     assm_->SetNextConstPoolCheckIn(1);
330   }
331 }
332 
333 
DistanceToFirstUse()334 int ConstPool::DistanceToFirstUse() {
335   DCHECK(first_use_ >= 0);
336   return assm_->pc_offset() - first_use_;
337 }
338 
339 
MaxPcOffset()340 int ConstPool::MaxPcOffset() {
341   // There are no pending entries in the pool so we can never get out of
342   // range.
343   if (IsEmpty()) return kMaxInt;
344 
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();
348 }
349 
350 
WorstCaseSize()351 int ConstPool::WorstCaseSize() {
352   if (IsEmpty()) return 0;
353 
354   // Max size prologue:
355   //   b   over
356   //   ldr xzr, #pool_size
357   //   blr xzr
358   //   nop
359   // All entries are 64-bit for now.
360   return 4 * kInstructionSize + EntryCount() * kPointerSize;
361 }
362 
363 
SizeIfEmittedAtCurrentPc(bool require_jump)364 int ConstPool::SizeIfEmittedAtCurrentPc(bool require_jump) {
365   if (IsEmpty()) return 0;
366 
367   // Prologue is:
368   //   b   over  ;; if require_jump
369   //   ldr xzr, #pool_size
370   //   blr xzr
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;
376 
377   // All entries are 64-bit for now.
378   return prologue_size + EntryCount() * kPointerSize;
379 }
380 
381 
Emit(bool require_jump)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_);
386 
387   int size = SizeIfEmittedAtCurrentPc(require_jump);
388   Label size_check;
389   assm_->bind(&size_check);
390 
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>
400   //   blr xzr
401   //   nop
402   //
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
408   // 64-bit aligned.
409 
410   // Emit branch if required
411   Label after_pool;
412   if (require_jump) {
413     assm_->b(&after_pool);
414   }
415 
416   // Emit the header.
417   assm_->RecordComment("[ Constant Pool");
418   EmitMarker();
419   EmitGuard();
420   assm_->Align(8);
421 
422   // Emit constant pool entries.
423   // TODO(all): currently each relocated constant is 64 bits, consider adding
424   // support for 32-bit entries.
425   EmitEntries();
426   assm_->RecordComment("]");
427 
428   if (after_pool.is_linked()) {
429     assm_->bind(&after_pool);
430   }
431 
432   DCHECK(assm_->SizeOfCodeGeneratedSince(&size_check) ==
433          static_cast<unsigned>(size));
434 }
435 
436 
Clear()437 void ConstPool::Clear() {
438   shared_entries_.clear();
439   shared_entries_count = 0;
440   unique_entries_.clear();
441   first_use_ = -1;
442 }
443 
444 
CanBeShared(RelocInfo::Mode mode)445 bool ConstPool::CanBeShared(RelocInfo::Mode mode) {
446   // Constant pool currently does not support 32-bit entries.
447   DCHECK(mode != RelocInfo::NONE32);
448 
449   return RelocInfo::IsNone(mode) ||
450          (!assm_->serializer_enabled() && (mode >= RelocInfo::CELL));
451 }
452 
453 
EmitMarker()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) |
463               Assembler::Rt(xzr));
464 }
465 
466 
AreConsistentForPair(const MemOperand & operandA,const MemOperand & operandB,int access_size_log2)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)) {
479     return kNotPair;
480   }
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)) {
485     return kPairAB;
486   }
487   if ((operandA.offset() == operandB.offset() + (1 << access_size_log2)) &&
488       is_int7(operandB.offset() >> access_size_log2)) {
489     return kPairBA;
490   }
491   return kNotPair;
492 }
493 
494 
EmitGuard()495 void ConstPool::EmitGuard() {
496 #ifdef DEBUG
497   Instruction* instr = reinterpret_cast<Instruction*>(assm_->pc());
498   DCHECK(instr->preceding()->IsLdrLiteralX() &&
499          instr->preceding()->Rt() == xzr.code());
500 #endif
501   assm_->EmitPoolGuard();
502 }
503 
504 
EmitEntries()505 void ConstPool::EmitEntries() {
506   DCHECK(IsAligned(assm_->pc_offset(), 8));
507 
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);
521 
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());
525     }
526     assm_->dc64(data);
527   }
528   shared_entries_.clear();
529   shared_entries_count = 0;
530 
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();
535        unique_it++) {
536     Instruction* instr = assm_->InstructionAt(unique_it->second);
537 
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);
542   }
543   unique_entries_.clear();
544   first_use_ = -1;
545 }
546 
547 
548 // Assembler
Assembler(Isolate * isolate,void * buffer,int buffer_size)549 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
550     : AssemblerBase(isolate, buffer, buffer_size),
551       constpool_(this),
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;
557   Reset();
558 }
559 
560 
~Assembler()561 Assembler::~Assembler() {
562   DCHECK(constpool_.IsEmpty());
563   DCHECK(const_pool_blocked_nesting_ == 0);
564   DCHECK(veneer_pool_blocked_nesting_ == 0);
565 }
566 
567 
Reset()568 void Assembler::Reset() {
569 #ifdef DEBUG
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_);
575 #endif
576   pc_ = buffer_;
577   reloc_info_writer.Reposition(reinterpret_cast<byte*>(buffer_ + buffer_size_),
578                                reinterpret_cast<byte*>(pc_));
579   constpool_.Clear();
580   next_constant_pool_check_ = 0;
581   next_veneer_pool_check_ = kMaxInt;
582   no_const_pool_before_ = 0;
583   ClearRecordedAstId();
584 }
585 
586 
GetCode(CodeDesc * desc)587 void Assembler::GetCode(CodeDesc* desc) {
588   // Emit constant pool if necessary.
589   CheckConstPool(true, false);
590   DCHECK(constpool_.IsEmpty());
591 
592   // Set up code descriptor.
593   if (desc) {
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();
599     desc->origin = this;
600   }
601 }
602 
603 
Align(int m)604 void Assembler::Align(int m) {
605   DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
606   while ((pc_offset() & (m - 1)) != 0) {
607     nop();
608   }
609 }
610 
611 
CheckLabelLinkChain(Label const * label)612 void Assembler::CheckLabelLinkChain(Label const * label) {
613 #ifdef DEBUG
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;
621 
622       end_of_chain = (linkoffset == prevlinkoffset);
623       linkoffset = linkoffset + linkpcoffset;
624     }
625   }
626 #endif
627 }
628 
629 
RemoveBranchFromLabelLinkChain(Instruction * branch,Label * label,Instruction * label_veneer)630 void Assembler::RemoveBranchFromLabelLinkChain(Instruction* branch,
631                                                Label* label,
632                                                Instruction* label_veneer) {
633   DCHECK(label->is_linked());
634 
635   CheckLabelLinkChain(label);
636 
637   Instruction* link = InstructionAt(label->pos());
638   Instruction* prev_link = link;
639   Instruction* next_link;
640   bool end_of_chain = false;
641 
642   while (link != branch && !end_of_chain) {
643     next_link = link->ImmPCOffsetTarget();
644     end_of_chain = (link == next_link);
645     prev_link = link;
646     link = next_link;
647   }
648 
649   DCHECK(branch == link);
650   next_link = branch->ImmPCOffsetTarget();
651 
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.
657       label->Unuse();
658     } else {
659       label->link_to(reinterpret_cast<byte*>(next_link) - buffer_);
660     }
661 
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);
665 
666   } else {
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);
673 
674       end_of_chain = false;
675       link = next_link;
676       while (!end_of_chain) {
677         next_link = link->ImmPCOffsetTarget();
678         end_of_chain = (link == next_link);
679         link->SetImmPCOffsetTarget(label_veneer);
680         link = next_link;
681       }
682     } else {
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.
687       //
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:
691       //    [previous code]
692       //    B(label);
693       //    [20KB code]
694       //    Tbz(label);   // First tbz. Pointing to unconditional branch.
695       //    [20KB code]
696       //    Tbz(label);   // Second tbz. Pointing to the first tbz.
697       //    [more code]
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));
702       UNREACHABLE();
703     }
704   }
705 
706   CheckLabelLinkChain(label);
707 }
708 
709 
bind(Label * 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
713   // label.
714 
715   DCHECK(!label->is_near_linked());
716   DCHECK(!label->is_bound());
717 
718   DeleteUnresolvedBranchInfoForLabel(label);
719 
720   // If the label is linked, the link chain looks something like this:
721   //
722   // |--I----I-------I-------L
723   // |---------------------->| pc_offset
724   // |-------------->|         linkoffset = label->pos()
725   //         |<------|         link->ImmPCOffset()
726   // |------>|                 prevlinkoffset = linkoffset + link->ImmPCOffset()
727   //
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.
730   //
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();
736 
737     CheckLabelLinkChain(label);
738 
739     DCHECK(linkoffset >= 0);
740     DCHECK(linkoffset < pc_offset());
741     DCHECK((linkoffset > prevlinkoffset) ||
742            (linkoffset - prevlinkoffset == kStartOfLabelLinkChain));
743     DCHECK(prevlinkoffset >= 0);
744 
745     // Update the link to point to the label.
746     link->SetImmPCOffsetTarget(reinterpret_cast<Instruction*>(pc_));
747 
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.
751       label->Unuse();
752     } else {
753       // Update the label for the next iteration.
754       label->link_to(prevlinkoffset);
755     }
756   }
757   label->bind_to(pc_offset());
758 
759   DCHECK(label->is_bound());
760   DCHECK(!label->is_linked());
761 }
762 
763 
LinkAndGetByteOffsetTo(Label * label)764 int Assembler::LinkAndGetByteOffsetTo(Label* label) {
765   DCHECK(sizeof(*pc_) == 1);
766   CheckLabelLinkChain(label);
767 
768   int offset;
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
772     // updated.
773     //
774     // In this case, label->pos() returns the offset of the label from the
775     // start of the buffer.
776     //
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();
780     DCHECK(offset <= 0);
781   } else {
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.
785       //
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.
794     } else {
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;
798     }
799     // The instruction at pc is now the last link in the label's chain.
800     label->link_to(pc_offset());
801   }
802 
803   return offset;
804 }
805 
806 
DeleteUnresolvedBranchInfoForLabelTraverse(Label * label)807 void Assembler::DeleteUnresolvedBranchInfoForLabelTraverse(Label* label) {
808   DCHECK(label->is_linked());
809   CheckLabelLinkChain(label);
810 
811   int link_offset = label->pos();
812   int link_pcoffset;
813   bool end_of_chain = false;
814 
815   while (!end_of_chain) {
816     Instruction * link = InstructionAt(link_offset);
817     link_pcoffset = link->ImmPCOffset();
818 
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);
830           break;
831         }
832       }
833     }
834 
835     end_of_chain = (link_pcoffset == 0);
836     link_offset = link_offset + link_pcoffset;
837   }
838 }
839 
840 
DeleteUnresolvedBranchInfoForLabel(Label * label)841 void Assembler::DeleteUnresolvedBranchInfoForLabel(Label* label) {
842   if (unresolved_branches_.empty()) {
843     DCHECK(next_veneer_pool_check_ == kMaxInt);
844     return;
845   }
846 
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);
851   }
852   if (unresolved_branches_.empty()) {
853     next_veneer_pool_check_ = kMaxInt;
854   } else {
855     next_veneer_pool_check_ =
856       unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
857   }
858 }
859 
860 
StartBlockConstPool()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;
866   }
867 }
868 
869 
EndBlockConstPool()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());
874     // Two cases:
875     //  * no_const_pool_before_ >= next_constant_pool_check_ and the emission is
876     //    still blocked
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_;
880   }
881 }
882 
883 
is_const_pool_blocked() const884 bool Assembler::is_const_pool_blocked() const {
885   return (const_pool_blocked_nesting_ > 0) ||
886          (pc_offset() < no_const_pool_before_);
887 }
888 
889 
IsConstantPoolAt(Instruction * instr)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());
895 
896   // It is still worth asserting the marker is complete.
897   // 4: blr xzr
898   DCHECK(!result || (instr->following()->IsBranchAndLinkToRegister() &&
899                      instr->following()->Rn() == xzr.code()));
900 
901   return result;
902 }
903 
904 
ConstantPoolSizeAt(Instruction * instr)905 int Assembler::ConstantPoolSizeAt(Instruction* instr) {
906 #ifdef USE_SIMULATOR
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;
917   }
918   // Same for printf support, see MacroAssembler::CallPrintf().
919   if ((instr->Mask(ExceptionMask) == HLT) &&
920       (instr->ImmException() == kImmExceptionIsPrintf)) {
921     return kPrintfLength / kInstructionSize;
922   }
923 #endif
924   if (IsConstantPoolAt(instr)) {
925     return instr->ImmLLiteral();
926   } else {
927     return -1;
928   }
929 }
930 
931 
EmitPoolGuard()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.
935   Emit(BLR | Rn(xzr));
936 }
937 
938 
StartBlockVeneerPool()939 void Assembler::StartBlockVeneerPool() {
940   ++veneer_pool_blocked_nesting_;
941 }
942 
943 
EndBlockVeneerPool()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()));
949   }
950 }
951 
952 
br(const Register & xn)953 void Assembler::br(const Register& xn) {
954   positions_recorder()->WriteRecordedPositions();
955   DCHECK(xn.Is64Bits());
956   Emit(BR | Rn(xn));
957 }
958 
959 
blr(const Register & xn)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.
965   DCHECK(!xn.Is(xzr));
966   Emit(BLR | Rn(xn));
967 }
968 
969 
ret(const Register & xn)970 void Assembler::ret(const Register& xn) {
971   positions_recorder()->WriteRecordedPositions();
972   DCHECK(xn.Is64Bits());
973   Emit(RET | Rn(xn));
974 }
975 
976 
b(int imm26)977 void Assembler::b(int imm26) {
978   Emit(B | ImmUncondBranch(imm26));
979 }
980 
981 
b(Label * label)982 void Assembler::b(Label* label) {
983   positions_recorder()->WriteRecordedPositions();
984   b(LinkAndGetInstructionOffsetTo(label));
985 }
986 
987 
b(int imm19,Condition cond)988 void Assembler::b(int imm19, Condition cond) {
989   Emit(B_cond | ImmCondBranch(imm19) | cond);
990 }
991 
992 
b(Label * label,Condition cond)993 void Assembler::b(Label* label, Condition cond) {
994   positions_recorder()->WriteRecordedPositions();
995   b(LinkAndGetInstructionOffsetTo(label), cond);
996 }
997 
998 
bl(int imm26)999 void Assembler::bl(int imm26) {
1000   positions_recorder()->WriteRecordedPositions();
1001   Emit(BL | ImmUncondBranch(imm26));
1002 }
1003 
1004 
bl(Label * label)1005 void Assembler::bl(Label* label) {
1006   positions_recorder()->WriteRecordedPositions();
1007   bl(LinkAndGetInstructionOffsetTo(label));
1008 }
1009 
1010 
cbz(const Register & rt,int imm19)1011 void Assembler::cbz(const Register& rt,
1012                     int imm19) {
1013   positions_recorder()->WriteRecordedPositions();
1014   Emit(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt));
1015 }
1016 
1017 
cbz(const Register & rt,Label * label)1018 void Assembler::cbz(const Register& rt,
1019                     Label* label) {
1020   positions_recorder()->WriteRecordedPositions();
1021   cbz(rt, LinkAndGetInstructionOffsetTo(label));
1022 }
1023 
1024 
cbnz(const Register & rt,int imm19)1025 void Assembler::cbnz(const Register& rt,
1026                      int imm19) {
1027   positions_recorder()->WriteRecordedPositions();
1028   Emit(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt));
1029 }
1030 
1031 
cbnz(const Register & rt,Label * label)1032 void Assembler::cbnz(const Register& rt,
1033                      Label* label) {
1034   positions_recorder()->WriteRecordedPositions();
1035   cbnz(rt, LinkAndGetInstructionOffsetTo(label));
1036 }
1037 
1038 
tbz(const Register & rt,unsigned bit_pos,int imm14)1039 void Assembler::tbz(const Register& rt,
1040                     unsigned bit_pos,
1041                     int imm14) {
1042   positions_recorder()->WriteRecordedPositions();
1043   DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
1044   Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
1045 }
1046 
1047 
tbz(const Register & rt,unsigned bit_pos,Label * label)1048 void Assembler::tbz(const Register& rt,
1049                     unsigned bit_pos,
1050                     Label* label) {
1051   positions_recorder()->WriteRecordedPositions();
1052   tbz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
1053 }
1054 
1055 
tbnz(const Register & rt,unsigned bit_pos,int imm14)1056 void Assembler::tbnz(const Register& rt,
1057                      unsigned bit_pos,
1058                      int imm14) {
1059   positions_recorder()->WriteRecordedPositions();
1060   DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
1061   Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
1062 }
1063 
1064 
tbnz(const Register & rt,unsigned bit_pos,Label * label)1065 void Assembler::tbnz(const Register& rt,
1066                      unsigned bit_pos,
1067                      Label* label) {
1068   positions_recorder()->WriteRecordedPositions();
1069   tbnz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
1070 }
1071 
1072 
adr(const Register & rd,int imm21)1073 void Assembler::adr(const Register& rd, int imm21) {
1074   DCHECK(rd.Is64Bits());
1075   Emit(ADR | ImmPCRelAddress(imm21) | Rd(rd));
1076 }
1077 
1078 
adr(const Register & rd,Label * label)1079 void Assembler::adr(const Register& rd, Label* label) {
1080   adr(rd, LinkAndGetByteOffsetTo(label));
1081 }
1082 
1083 
add(const Register & rd,const Register & rn,const Operand & operand)1084 void Assembler::add(const Register& rd,
1085                     const Register& rn,
1086                     const Operand& operand) {
1087   AddSub(rd, rn, operand, LeaveFlags, ADD);
1088 }
1089 
1090 
adds(const Register & rd,const Register & rn,const Operand & operand)1091 void Assembler::adds(const Register& rd,
1092                      const Register& rn,
1093                      const Operand& operand) {
1094   AddSub(rd, rn, operand, SetFlags, ADD);
1095 }
1096 
1097 
cmn(const Register & rn,const Operand & operand)1098 void Assembler::cmn(const Register& rn,
1099                     const Operand& operand) {
1100   Register zr = AppropriateZeroRegFor(rn);
1101   adds(zr, rn, operand);
1102 }
1103 
1104 
sub(const Register & rd,const Register & rn,const Operand & operand)1105 void Assembler::sub(const Register& rd,
1106                     const Register& rn,
1107                     const Operand& operand) {
1108   AddSub(rd, rn, operand, LeaveFlags, SUB);
1109 }
1110 
1111 
subs(const Register & rd,const Register & rn,const Operand & operand)1112 void Assembler::subs(const Register& rd,
1113                      const Register& rn,
1114                      const Operand& operand) {
1115   AddSub(rd, rn, operand, SetFlags, SUB);
1116 }
1117 
1118 
cmp(const Register & rn,const Operand & operand)1119 void Assembler::cmp(const Register& rn, const Operand& operand) {
1120   Register zr = AppropriateZeroRegFor(rn);
1121   subs(zr, rn, operand);
1122 }
1123 
1124 
neg(const Register & rd,const Operand & operand)1125 void Assembler::neg(const Register& rd, const Operand& operand) {
1126   Register zr = AppropriateZeroRegFor(rd);
1127   sub(rd, zr, operand);
1128 }
1129 
1130 
negs(const Register & rd,const Operand & operand)1131 void Assembler::negs(const Register& rd, const Operand& operand) {
1132   Register zr = AppropriateZeroRegFor(rd);
1133   subs(rd, zr, operand);
1134 }
1135 
1136 
adc(const Register & rd,const Register & rn,const Operand & operand)1137 void Assembler::adc(const Register& rd,
1138                     const Register& rn,
1139                     const Operand& operand) {
1140   AddSubWithCarry(rd, rn, operand, LeaveFlags, ADC);
1141 }
1142 
1143 
adcs(const Register & rd,const Register & rn,const Operand & operand)1144 void Assembler::adcs(const Register& rd,
1145                      const Register& rn,
1146                      const Operand& operand) {
1147   AddSubWithCarry(rd, rn, operand, SetFlags, ADC);
1148 }
1149 
1150 
sbc(const Register & rd,const Register & rn,const Operand & operand)1151 void Assembler::sbc(const Register& rd,
1152                     const Register& rn,
1153                     const Operand& operand) {
1154   AddSubWithCarry(rd, rn, operand, LeaveFlags, SBC);
1155 }
1156 
1157 
sbcs(const Register & rd,const Register & rn,const Operand & operand)1158 void Assembler::sbcs(const Register& rd,
1159                      const Register& rn,
1160                      const Operand& operand) {
1161   AddSubWithCarry(rd, rn, operand, SetFlags, SBC);
1162 }
1163 
1164 
ngc(const Register & rd,const Operand & operand)1165 void Assembler::ngc(const Register& rd, const Operand& operand) {
1166   Register zr = AppropriateZeroRegFor(rd);
1167   sbc(rd, zr, operand);
1168 }
1169 
1170 
ngcs(const Register & rd,const Operand & operand)1171 void Assembler::ngcs(const Register& rd, const Operand& operand) {
1172   Register zr = AppropriateZeroRegFor(rd);
1173   sbcs(rd, zr, operand);
1174 }
1175 
1176 
1177 // Logical instructions.
and_(const Register & rd,const Register & rn,const Operand & operand)1178 void Assembler::and_(const Register& rd,
1179                      const Register& rn,
1180                      const Operand& operand) {
1181   Logical(rd, rn, operand, AND);
1182 }
1183 
1184 
ands(const Register & rd,const Register & rn,const Operand & operand)1185 void Assembler::ands(const Register& rd,
1186                      const Register& rn,
1187                      const Operand& operand) {
1188   Logical(rd, rn, operand, ANDS);
1189 }
1190 
1191 
tst(const Register & rn,const Operand & operand)1192 void Assembler::tst(const Register& rn,
1193                     const Operand& operand) {
1194   ands(AppropriateZeroRegFor(rn), rn, operand);
1195 }
1196 
1197 
bic(const Register & rd,const Register & rn,const Operand & operand)1198 void Assembler::bic(const Register& rd,
1199                     const Register& rn,
1200                     const Operand& operand) {
1201   Logical(rd, rn, operand, BIC);
1202 }
1203 
1204 
bics(const Register & rd,const Register & rn,const Operand & operand)1205 void Assembler::bics(const Register& rd,
1206                      const Register& rn,
1207                      const Operand& operand) {
1208   Logical(rd, rn, operand, BICS);
1209 }
1210 
1211 
orr(const Register & rd,const Register & rn,const Operand & operand)1212 void Assembler::orr(const Register& rd,
1213                     const Register& rn,
1214                     const Operand& operand) {
1215   Logical(rd, rn, operand, ORR);
1216 }
1217 
1218 
orn(const Register & rd,const Register & rn,const Operand & operand)1219 void Assembler::orn(const Register& rd,
1220                     const Register& rn,
1221                     const Operand& operand) {
1222   Logical(rd, rn, operand, ORN);
1223 }
1224 
1225 
eor(const Register & rd,const Register & rn,const Operand & operand)1226 void Assembler::eor(const Register& rd,
1227                     const Register& rn,
1228                     const Operand& operand) {
1229   Logical(rd, rn, operand, EOR);
1230 }
1231 
1232 
eon(const Register & rd,const Register & rn,const Operand & operand)1233 void Assembler::eon(const Register& rd,
1234                     const Register& rn,
1235                     const Operand& operand) {
1236   Logical(rd, rn, operand, EON);
1237 }
1238 
1239 
lslv(const Register & rd,const Register & rn,const Register & rm)1240 void Assembler::lslv(const Register& rd,
1241                      const Register& rn,
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));
1246 }
1247 
1248 
lsrv(const Register & rd,const Register & rn,const Register & rm)1249 void Assembler::lsrv(const Register& rd,
1250                      const Register& rn,
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));
1255 }
1256 
1257 
asrv(const Register & rd,const Register & rn,const Register & rm)1258 void Assembler::asrv(const Register& rd,
1259                      const Register& rn,
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));
1264 }
1265 
1266 
rorv(const Register & rd,const Register & rn,const Register & rm)1267 void Assembler::rorv(const Register& rd,
1268                      const Register& rn,
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));
1273 }
1274 
1275 
1276 // Bitfield operations.
bfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)1277 void Assembler::bfm(const Register& rd,
1278                      const Register& rn,
1279                      unsigned immr,
1280                      unsigned imms) {
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()) |
1286        Rn(rn) | Rd(rd));
1287 }
1288 
1289 
sbfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)1290 void Assembler::sbfm(const Register& rd,
1291                      const Register& rn,
1292                      unsigned immr,
1293                      unsigned imms) {
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()) |
1299        Rn(rn) | Rd(rd));
1300 }
1301 
1302 
ubfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)1303 void Assembler::ubfm(const Register& rd,
1304                      const Register& rn,
1305                      unsigned immr,
1306                      unsigned imms) {
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()) |
1312        Rn(rn) | Rd(rd));
1313 }
1314 
1315 
extr(const Register & rd,const Register & rn,const Register & rm,unsigned lsb)1316 void Assembler::extr(const Register& rd,
1317                      const Register& rn,
1318                      const Register& rm,
1319                      unsigned lsb) {
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));
1325 }
1326 
1327 
csel(const Register & rd,const Register & rn,const Register & rm,Condition cond)1328 void Assembler::csel(const Register& rd,
1329                      const Register& rn,
1330                      const Register& rm,
1331                      Condition cond) {
1332   ConditionalSelect(rd, rn, rm, cond, CSEL);
1333 }
1334 
1335 
csinc(const Register & rd,const Register & rn,const Register & rm,Condition cond)1336 void Assembler::csinc(const Register& rd,
1337                       const Register& rn,
1338                       const Register& rm,
1339                       Condition cond) {
1340   ConditionalSelect(rd, rn, rm, cond, CSINC);
1341 }
1342 
1343 
csinv(const Register & rd,const Register & rn,const Register & rm,Condition cond)1344 void Assembler::csinv(const Register& rd,
1345                       const Register& rn,
1346                       const Register& rm,
1347                       Condition cond) {
1348   ConditionalSelect(rd, rn, rm, cond, CSINV);
1349 }
1350 
1351 
csneg(const Register & rd,const Register & rn,const Register & rm,Condition cond)1352 void Assembler::csneg(const Register& rd,
1353                       const Register& rn,
1354                       const Register& rm,
1355                       Condition cond) {
1356   ConditionalSelect(rd, rn, rm, cond, CSNEG);
1357 }
1358 
1359 
cset(const Register & rd,Condition cond)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));
1364 }
1365 
1366 
csetm(const Register & rd,Condition 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));
1371 }
1372 
1373 
cinc(const Register & rd,const Register & rn,Condition 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));
1377 }
1378 
1379 
cinv(const Register & rd,const Register & rn,Condition 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));
1383 }
1384 
1385 
cneg(const Register & rd,const Register & rn,Condition 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));
1389 }
1390 
1391 
ConditionalSelect(const Register & rd,const Register & rn,const Register & rm,Condition cond,ConditionalSelectOp op)1392 void Assembler::ConditionalSelect(const Register& rd,
1393                                   const Register& rn,
1394                                   const Register& rm,
1395                                   Condition cond,
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));
1400 }
1401 
1402 
ccmn(const Register & rn,const Operand & operand,StatusFlags nzcv,Condition cond)1403 void Assembler::ccmn(const Register& rn,
1404                      const Operand& operand,
1405                      StatusFlags nzcv,
1406                      Condition cond) {
1407   ConditionalCompare(rn, operand, nzcv, cond, CCMN);
1408 }
1409 
1410 
ccmp(const Register & rn,const Operand & operand,StatusFlags nzcv,Condition cond)1411 void Assembler::ccmp(const Register& rn,
1412                      const Operand& operand,
1413                      StatusFlags nzcv,
1414                      Condition cond) {
1415   ConditionalCompare(rn, operand, nzcv, cond, CCMP);
1416 }
1417 
1418 
DataProcessing3Source(const Register & rd,const Register & rn,const Register & rm,const Register & ra,DataProcessing3SourceOp op)1419 void Assembler::DataProcessing3Source(const Register& rd,
1420                                       const Register& rn,
1421                                       const Register& rm,
1422                                       const Register& ra,
1423                                       DataProcessing3SourceOp op) {
1424   Emit(SF(rd) | op | Rm(rm) | Ra(ra) | Rn(rn) | Rd(rd));
1425 }
1426 
1427 
mul(const Register & rd,const Register & rn,const Register & rm)1428 void Assembler::mul(const Register& rd,
1429                     const Register& rn,
1430                     const Register& rm) {
1431   DCHECK(AreSameSizeAndType(rd, rn, rm));
1432   Register zr = AppropriateZeroRegFor(rn);
1433   DataProcessing3Source(rd, rn, rm, zr, MADD);
1434 }
1435 
1436 
madd(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1437 void Assembler::madd(const Register& rd,
1438                      const Register& rn,
1439                      const Register& rm,
1440                      const Register& ra) {
1441   DCHECK(AreSameSizeAndType(rd, rn, rm, ra));
1442   DataProcessing3Source(rd, rn, rm, ra, MADD);
1443 }
1444 
1445 
mneg(const Register & rd,const Register & rn,const Register & rm)1446 void Assembler::mneg(const Register& rd,
1447                      const Register& rn,
1448                      const Register& rm) {
1449   DCHECK(AreSameSizeAndType(rd, rn, rm));
1450   Register zr = AppropriateZeroRegFor(rn);
1451   DataProcessing3Source(rd, rn, rm, zr, MSUB);
1452 }
1453 
1454 
msub(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1455 void Assembler::msub(const Register& rd,
1456                      const Register& rn,
1457                      const Register& rm,
1458                      const Register& ra) {
1459   DCHECK(AreSameSizeAndType(rd, rn, rm, ra));
1460   DataProcessing3Source(rd, rn, rm, ra, MSUB);
1461 }
1462 
1463 
smaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1464 void Assembler::smaddl(const Register& rd,
1465                        const Register& rn,
1466                        const Register& rm,
1467                        const Register& ra) {
1468   DCHECK(rd.Is64Bits() && ra.Is64Bits());
1469   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1470   DataProcessing3Source(rd, rn, rm, ra, SMADDL_x);
1471 }
1472 
1473 
smsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1474 void Assembler::smsubl(const Register& rd,
1475                        const Register& rn,
1476                        const Register& rm,
1477                        const Register& ra) {
1478   DCHECK(rd.Is64Bits() && ra.Is64Bits());
1479   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1480   DataProcessing3Source(rd, rn, rm, ra, SMSUBL_x);
1481 }
1482 
1483 
umaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1484 void Assembler::umaddl(const Register& rd,
1485                        const Register& rn,
1486                        const Register& rm,
1487                        const Register& ra) {
1488   DCHECK(rd.Is64Bits() && ra.Is64Bits());
1489   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1490   DataProcessing3Source(rd, rn, rm, ra, UMADDL_x);
1491 }
1492 
1493 
umsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1494 void Assembler::umsubl(const Register& rd,
1495                        const Register& rn,
1496                        const Register& rm,
1497                        const Register& ra) {
1498   DCHECK(rd.Is64Bits() && ra.Is64Bits());
1499   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1500   DataProcessing3Source(rd, rn, rm, ra, UMSUBL_x);
1501 }
1502 
1503 
smull(const Register & rd,const Register & rn,const Register & rm)1504 void Assembler::smull(const Register& rd,
1505                       const Register& rn,
1506                       const Register& rm) {
1507   DCHECK(rd.Is64Bits());
1508   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1509   DataProcessing3Source(rd, rn, rm, xzr, SMADDL_x);
1510 }
1511 
1512 
smulh(const Register & rd,const Register & rn,const Register & rm)1513 void Assembler::smulh(const Register& rd,
1514                       const Register& rn,
1515                       const Register& rm) {
1516   DCHECK(AreSameSizeAndType(rd, rn, rm));
1517   DataProcessing3Source(rd, rn, rm, xzr, SMULH_x);
1518 }
1519 
1520 
sdiv(const Register & rd,const Register & rn,const Register & rm)1521 void Assembler::sdiv(const Register& rd,
1522                      const Register& rn,
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));
1527 }
1528 
1529 
udiv(const Register & rd,const Register & rn,const Register & rm)1530 void Assembler::udiv(const Register& rd,
1531                      const Register& rn,
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));
1536 }
1537 
1538 
rbit(const Register & rd,const Register & rn)1539 void Assembler::rbit(const Register& rd,
1540                      const Register& rn) {
1541   DataProcessing1Source(rd, rn, RBIT);
1542 }
1543 
1544 
rev16(const Register & rd,const Register & rn)1545 void Assembler::rev16(const Register& rd,
1546                       const Register& rn) {
1547   DataProcessing1Source(rd, rn, REV16);
1548 }
1549 
1550 
rev32(const Register & rd,const Register & rn)1551 void Assembler::rev32(const Register& rd,
1552                       const Register& rn) {
1553   DCHECK(rd.Is64Bits());
1554   DataProcessing1Source(rd, rn, REV);
1555 }
1556 
1557 
rev(const Register & rd,const Register & rn)1558 void Assembler::rev(const Register& rd,
1559                     const Register& rn) {
1560   DataProcessing1Source(rd, rn, rd.Is64Bits() ? REV_x : REV_w);
1561 }
1562 
1563 
clz(const Register & rd,const Register & rn)1564 void Assembler::clz(const Register& rd,
1565                     const Register& rn) {
1566   DataProcessing1Source(rd, rn, CLZ);
1567 }
1568 
1569 
cls(const Register & rd,const Register & rn)1570 void Assembler::cls(const Register& rd,
1571                     const Register& rn) {
1572   DataProcessing1Source(rd, rn, CLS);
1573 }
1574 
1575 
ldp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & src)1576 void Assembler::ldp(const CPURegister& rt,
1577                     const CPURegister& rt2,
1578                     const MemOperand& src) {
1579   LoadStorePair(rt, rt2, src, LoadPairOpFor(rt, rt2));
1580 }
1581 
1582 
stp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & dst)1583 void Assembler::stp(const CPURegister& rt,
1584                     const CPURegister& rt2,
1585                     const MemOperand& dst) {
1586   LoadStorePair(rt, rt2, dst, StorePairOpFor(rt, rt2));
1587 }
1588 
1589 
ldpsw(const Register & rt,const Register & rt2,const MemOperand & src)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);
1595 }
1596 
1597 
LoadStorePair(const CPURegister & rt,const CPURegister & rt2,const MemOperand & addr,LoadStorePairOp op)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));
1605 
1606   Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
1607                 ImmLSPair(addr.offset(), CalcLSPairDataSize(op));
1608 
1609   Instr addrmodeop;
1610   if (addr.IsImmediateOffset()) {
1611     addrmodeop = LoadStorePairOffsetFixed;
1612   } else {
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;
1619     } else {
1620       DCHECK(addr.IsPostIndex());
1621       addrmodeop = LoadStorePairPostIndexFixed;
1622     }
1623   }
1624   Emit(addrmodeop | memop);
1625 }
1626 
1627 
ldnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & src)1628 void Assembler::ldnp(const CPURegister& rt,
1629                      const CPURegister& rt2,
1630                      const MemOperand& src) {
1631   LoadStorePairNonTemporal(rt, rt2, src,
1632                            LoadPairNonTemporalOpFor(rt, rt2));
1633 }
1634 
1635 
stnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & dst)1636 void Assembler::stnp(const CPURegister& rt,
1637                      const CPURegister& rt2,
1638                      const MemOperand& dst) {
1639   LoadStorePairNonTemporal(rt, rt2, dst,
1640                            StorePairNonTemporalOpFor(rt, rt2));
1641 }
1642 
1643 
LoadStorePairNonTemporal(const CPURegister & rt,const CPURegister & rt2,const MemOperand & addr,LoadStorePairNonTemporalOp op)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());
1651 
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));
1656 }
1657 
1658 
1659 // Memory instructions.
ldrb(const Register & rt,const MemOperand & src)1660 void Assembler::ldrb(const Register& rt, const MemOperand& src) {
1661   LoadStore(rt, src, LDRB_w);
1662 }
1663 
1664 
strb(const Register & rt,const MemOperand & dst)1665 void Assembler::strb(const Register& rt, const MemOperand& dst) {
1666   LoadStore(rt, dst, STRB_w);
1667 }
1668 
1669 
ldrsb(const Register & rt,const MemOperand & src)1670 void Assembler::ldrsb(const Register& rt, const MemOperand& src) {
1671   LoadStore(rt, src, rt.Is64Bits() ? LDRSB_x : LDRSB_w);
1672 }
1673 
1674 
ldrh(const Register & rt,const MemOperand & src)1675 void Assembler::ldrh(const Register& rt, const MemOperand& src) {
1676   LoadStore(rt, src, LDRH_w);
1677 }
1678 
1679 
strh(const Register & rt,const MemOperand & dst)1680 void Assembler::strh(const Register& rt, const MemOperand& dst) {
1681   LoadStore(rt, dst, STRH_w);
1682 }
1683 
1684 
ldrsh(const Register & rt,const MemOperand & src)1685 void Assembler::ldrsh(const Register& rt, const MemOperand& src) {
1686   LoadStore(rt, src, rt.Is64Bits() ? LDRSH_x : LDRSH_w);
1687 }
1688 
1689 
ldr(const CPURegister & rt,const MemOperand & src)1690 void Assembler::ldr(const CPURegister& rt, const MemOperand& src) {
1691   LoadStore(rt, src, LoadOpFor(rt));
1692 }
1693 
1694 
str(const CPURegister & rt,const MemOperand & src)1695 void Assembler::str(const CPURegister& rt, const MemOperand& src) {
1696   LoadStore(rt, src, StoreOpFor(rt));
1697 }
1698 
1699 
ldrsw(const Register & rt,const MemOperand & src)1700 void Assembler::ldrsw(const Register& rt, const MemOperand& src) {
1701   DCHECK(rt.Is64Bits());
1702   LoadStore(rt, src, LDRSW_x);
1703 }
1704 
1705 
ldr_pcrel(const CPURegister & rt,int imm19)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));
1711 }
1712 
1713 
ldr(const CPURegister & rt,const Immediate & imm)1714 void Assembler::ldr(const CPURegister& rt, const Immediate& imm) {
1715   // Currently we only support 64-bit literals.
1716   DCHECK(rt.Is64Bits());
1717 
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.
1722   ldr_pcrel(rt, 0);
1723 }
1724 
1725 
mov(const Register & rd,const Register & rm)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
1729   // used.
1730   if (rd.IsSP() || rm.IsSP()) {
1731     add(rd, rm, 0);
1732   } else {
1733     orr(rd, AppropriateZeroRegFor(rd), rm);
1734   }
1735 }
1736 
1737 
mvn(const Register & rd,const Operand & operand)1738 void Assembler::mvn(const Register& rd, const Operand& operand) {
1739   orn(rd, AppropriateZeroRegFor(rd), operand);
1740 }
1741 
1742 
mrs(const Register & rt,SystemRegister sysreg)1743 void Assembler::mrs(const Register& rt, SystemRegister sysreg) {
1744   DCHECK(rt.Is64Bits());
1745   Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt));
1746 }
1747 
1748 
msr(SystemRegister sysreg,const Register & rt)1749 void Assembler::msr(SystemRegister sysreg, const Register& rt) {
1750   DCHECK(rt.Is64Bits());
1751   Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg));
1752 }
1753 
1754 
hint(SystemHint code)1755 void Assembler::hint(SystemHint code) {
1756   Emit(HINT | ImmHint(code) | Rt(xzr));
1757 }
1758 
1759 
dmb(BarrierDomain domain,BarrierType type)1760 void Assembler::dmb(BarrierDomain domain, BarrierType type) {
1761   Emit(DMB | ImmBarrierDomain(domain) | ImmBarrierType(type));
1762 }
1763 
1764 
dsb(BarrierDomain domain,BarrierType type)1765 void Assembler::dsb(BarrierDomain domain, BarrierType type) {
1766   Emit(DSB | ImmBarrierDomain(domain) | ImmBarrierType(type));
1767 }
1768 
1769 
isb()1770 void Assembler::isb() {
1771   Emit(ISB | ImmBarrierDomain(FullSystem) | ImmBarrierType(BarrierAll));
1772 }
1773 
1774 
fmov(FPRegister fd,double imm)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));
1779 }
1780 
1781 
fmov(FPRegister fd,float 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));
1786 }
1787 
1788 
fmov(Register rd,FPRegister fn)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));
1793 }
1794 
1795 
fmov(FPRegister fd,Register rn)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));
1800 }
1801 
1802 
fmov(FPRegister fd,FPRegister fn)1803 void Assembler::fmov(FPRegister fd, FPRegister fn) {
1804   DCHECK(fd.SizeInBits() == fn.SizeInBits());
1805   Emit(FPType(fd) | FMOV | Rd(fd) | Rn(fn));
1806 }
1807 
1808 
fadd(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)1809 void Assembler::fadd(const FPRegister& fd,
1810                      const FPRegister& fn,
1811                      const FPRegister& fm) {
1812   FPDataProcessing2Source(fd, fn, fm, FADD);
1813 }
1814 
1815 
fsub(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)1816 void Assembler::fsub(const FPRegister& fd,
1817                      const FPRegister& fn,
1818                      const FPRegister& fm) {
1819   FPDataProcessing2Source(fd, fn, fm, FSUB);
1820 }
1821 
1822 
fmul(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)1823 void Assembler::fmul(const FPRegister& fd,
1824                      const FPRegister& fn,
1825                      const FPRegister& fm) {
1826   FPDataProcessing2Source(fd, fn, fm, FMUL);
1827 }
1828 
1829 
fmadd(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,const FPRegister & fa)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);
1835 }
1836 
1837 
fmsub(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,const FPRegister & fa)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);
1843 }
1844 
1845 
fnmadd(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,const FPRegister & fa)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);
1851 }
1852 
1853 
fnmsub(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,const FPRegister & fa)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);
1859 }
1860 
1861 
fdiv(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)1862 void Assembler::fdiv(const FPRegister& fd,
1863                      const FPRegister& fn,
1864                      const FPRegister& fm) {
1865   FPDataProcessing2Source(fd, fn, fm, FDIV);
1866 }
1867 
1868 
fmax(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)1869 void Assembler::fmax(const FPRegister& fd,
1870                      const FPRegister& fn,
1871                      const FPRegister& fm) {
1872   FPDataProcessing2Source(fd, fn, fm, FMAX);
1873 }
1874 
1875 
fmaxnm(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)1876 void Assembler::fmaxnm(const FPRegister& fd,
1877                        const FPRegister& fn,
1878                        const FPRegister& fm) {
1879   FPDataProcessing2Source(fd, fn, fm, FMAXNM);
1880 }
1881 
1882 
fmin(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)1883 void Assembler::fmin(const FPRegister& fd,
1884                      const FPRegister& fn,
1885                      const FPRegister& fm) {
1886   FPDataProcessing2Source(fd, fn, fm, FMIN);
1887 }
1888 
1889 
fminnm(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)1890 void Assembler::fminnm(const FPRegister& fd,
1891                        const FPRegister& fn,
1892                        const FPRegister& fm) {
1893   FPDataProcessing2Source(fd, fn, fm, FMINNM);
1894 }
1895 
1896 
fabs(const FPRegister & fd,const FPRegister & fn)1897 void Assembler::fabs(const FPRegister& fd,
1898                      const FPRegister& fn) {
1899   DCHECK(fd.SizeInBits() == fn.SizeInBits());
1900   FPDataProcessing1Source(fd, fn, FABS);
1901 }
1902 
1903 
fneg(const FPRegister & fd,const FPRegister & fn)1904 void Assembler::fneg(const FPRegister& fd,
1905                      const FPRegister& fn) {
1906   DCHECK(fd.SizeInBits() == fn.SizeInBits());
1907   FPDataProcessing1Source(fd, fn, FNEG);
1908 }
1909 
1910 
fsqrt(const FPRegister & fd,const FPRegister & fn)1911 void Assembler::fsqrt(const FPRegister& fd,
1912                       const FPRegister& fn) {
1913   DCHECK(fd.SizeInBits() == fn.SizeInBits());
1914   FPDataProcessing1Source(fd, fn, FSQRT);
1915 }
1916 
1917 
frinta(const FPRegister & fd,const FPRegister & fn)1918 void Assembler::frinta(const FPRegister& fd,
1919                        const FPRegister& fn) {
1920   DCHECK(fd.SizeInBits() == fn.SizeInBits());
1921   FPDataProcessing1Source(fd, fn, FRINTA);
1922 }
1923 
1924 
frintm(const FPRegister & fd,const FPRegister & fn)1925 void Assembler::frintm(const FPRegister& fd,
1926                        const FPRegister& fn) {
1927   DCHECK(fd.SizeInBits() == fn.SizeInBits());
1928   FPDataProcessing1Source(fd, fn, FRINTM);
1929 }
1930 
1931 
frintn(const FPRegister & fd,const FPRegister & fn)1932 void Assembler::frintn(const FPRegister& fd,
1933                        const FPRegister& fn) {
1934   DCHECK(fd.SizeInBits() == fn.SizeInBits());
1935   FPDataProcessing1Source(fd, fn, FRINTN);
1936 }
1937 
1938 
frintz(const FPRegister & fd,const FPRegister & fn)1939 void Assembler::frintz(const FPRegister& fd,
1940                        const FPRegister& fn) {
1941   DCHECK(fd.SizeInBits() == fn.SizeInBits());
1942   FPDataProcessing1Source(fd, fn, FRINTZ);
1943 }
1944 
1945 
fcmp(const FPRegister & fn,const FPRegister & fm)1946 void Assembler::fcmp(const FPRegister& fn,
1947                      const FPRegister& fm) {
1948   DCHECK(fn.SizeInBits() == fm.SizeInBits());
1949   Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn));
1950 }
1951 
1952 
fcmp(const FPRegister & fn,double value)1953 void Assembler::fcmp(const FPRegister& fn,
1954                      double value) {
1955   USE(value);
1956   // Although the fcmp instruction can strictly only take an immediate value of
1957   // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't
1958   // affect the result of the comparison.
1959   DCHECK(value == 0.0);
1960   Emit(FPType(fn) | FCMP_zero | Rn(fn));
1961 }
1962 
1963 
fccmp(const FPRegister & fn,const FPRegister & fm,StatusFlags nzcv,Condition cond)1964 void Assembler::fccmp(const FPRegister& fn,
1965                       const FPRegister& fm,
1966                       StatusFlags nzcv,
1967                       Condition cond) {
1968   DCHECK(fn.SizeInBits() == fm.SizeInBits());
1969   Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv));
1970 }
1971 
1972 
fcsel(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,Condition cond)1973 void Assembler::fcsel(const FPRegister& fd,
1974                       const FPRegister& fn,
1975                       const FPRegister& fm,
1976                       Condition cond) {
1977   DCHECK(fd.SizeInBits() == fn.SizeInBits());
1978   DCHECK(fd.SizeInBits() == fm.SizeInBits());
1979   Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd));
1980 }
1981 
1982 
FPConvertToInt(const Register & rd,const FPRegister & fn,FPIntegerConvertOp op)1983 void Assembler::FPConvertToInt(const Register& rd,
1984                                const FPRegister& fn,
1985                                FPIntegerConvertOp op) {
1986   Emit(SF(rd) | FPType(fn) | op | Rn(fn) | Rd(rd));
1987 }
1988 
1989 
fcvt(const FPRegister & fd,const FPRegister & fn)1990 void Assembler::fcvt(const FPRegister& fd,
1991                      const FPRegister& fn) {
1992   if (fd.Is64Bits()) {
1993     // Convert float to double.
1994     DCHECK(fn.Is32Bits());
1995     FPDataProcessing1Source(fd, fn, FCVT_ds);
1996   } else {
1997     // Convert double to float.
1998     DCHECK(fn.Is64Bits());
1999     FPDataProcessing1Source(fd, fn, FCVT_sd);
2000   }
2001 }
2002 
2003 
fcvtau(const Register & rd,const FPRegister & fn)2004 void Assembler::fcvtau(const Register& rd, const FPRegister& fn) {
2005   FPConvertToInt(rd, fn, FCVTAU);
2006 }
2007 
2008 
fcvtas(const Register & rd,const FPRegister & fn)2009 void Assembler::fcvtas(const Register& rd, const FPRegister& fn) {
2010   FPConvertToInt(rd, fn, FCVTAS);
2011 }
2012 
2013 
fcvtmu(const Register & rd,const FPRegister & fn)2014 void Assembler::fcvtmu(const Register& rd, const FPRegister& fn) {
2015   FPConvertToInt(rd, fn, FCVTMU);
2016 }
2017 
2018 
fcvtms(const Register & rd,const FPRegister & fn)2019 void Assembler::fcvtms(const Register& rd, const FPRegister& fn) {
2020   FPConvertToInt(rd, fn, FCVTMS);
2021 }
2022 
2023 
fcvtnu(const Register & rd,const FPRegister & fn)2024 void Assembler::fcvtnu(const Register& rd, const FPRegister& fn) {
2025   FPConvertToInt(rd, fn, FCVTNU);
2026 }
2027 
2028 
fcvtns(const Register & rd,const FPRegister & fn)2029 void Assembler::fcvtns(const Register& rd, const FPRegister& fn) {
2030   FPConvertToInt(rd, fn, FCVTNS);
2031 }
2032 
2033 
fcvtzu(const Register & rd,const FPRegister & fn)2034 void Assembler::fcvtzu(const Register& rd, const FPRegister& fn) {
2035   FPConvertToInt(rd, fn, FCVTZU);
2036 }
2037 
2038 
fcvtzs(const Register & rd,const FPRegister & fn)2039 void Assembler::fcvtzs(const Register& rd, const FPRegister& fn) {
2040   FPConvertToInt(rd, fn, FCVTZS);
2041 }
2042 
2043 
scvtf(const FPRegister & fd,const Register & rn,unsigned fbits)2044 void Assembler::scvtf(const FPRegister& fd,
2045                       const Register& rn,
2046                       unsigned fbits) {
2047   if (fbits == 0) {
2048     Emit(SF(rn) | FPType(fd) | SCVTF | Rn(rn) | Rd(fd));
2049   } else {
2050     Emit(SF(rn) | FPType(fd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
2051          Rd(fd));
2052   }
2053 }
2054 
2055 
ucvtf(const FPRegister & fd,const Register & rn,unsigned fbits)2056 void Assembler::ucvtf(const FPRegister& fd,
2057                       const Register& rn,
2058                       unsigned fbits) {
2059   if (fbits == 0) {
2060     Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd));
2061   } else {
2062     Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
2063          Rd(fd));
2064   }
2065 }
2066 
2067 
2068 // Note:
2069 // Below, a difference in case for the same letter indicates a
2070 // negated bit.
2071 // If b is 1, then B is 0.
ImmFP32(float imm)2072 Instr Assembler::ImmFP32(float imm) {
2073   DCHECK(IsImmFP32(imm));
2074   // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000
2075   uint32_t bits = float_to_rawbits(imm);
2076   // bit7: a000.0000
2077   uint32_t bit7 = ((bits >> 31) & 0x1) << 7;
2078   // bit6: 0b00.0000
2079   uint32_t bit6 = ((bits >> 29) & 0x1) << 6;
2080   // bit5_to_0: 00cd.efgh
2081   uint32_t bit5_to_0 = (bits >> 19) & 0x3f;
2082 
2083   return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
2084 }
2085 
2086 
ImmFP64(double imm)2087 Instr Assembler::ImmFP64(double imm) {
2088   DCHECK(IsImmFP64(imm));
2089   // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2090   //       0000.0000.0000.0000.0000.0000.0000.0000
2091   uint64_t bits = double_to_rawbits(imm);
2092   // bit7: a000.0000
2093   uint32_t bit7 = ((bits >> 63) & 0x1) << 7;
2094   // bit6: 0b00.0000
2095   uint32_t bit6 = ((bits >> 61) & 0x1) << 6;
2096   // bit5_to_0: 00cd.efgh
2097   uint32_t bit5_to_0 = (bits >> 48) & 0x3f;
2098 
2099   return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
2100 }
2101 
2102 
2103 // Code generation helpers.
MoveWide(const Register & rd,uint64_t imm,int shift,MoveWideImmediateOp mov_op)2104 void Assembler::MoveWide(const Register& rd,
2105                          uint64_t imm,
2106                          int shift,
2107                          MoveWideImmediateOp mov_op) {
2108   // Ignore the top 32 bits of an immediate if we're moving to a W register.
2109   if (rd.Is32Bits()) {
2110     // Check that the top 32 bits are zero (a positive 32-bit number) or top
2111     // 33 bits are one (a negative 32-bit number, sign extended to 64 bits).
2112     DCHECK(((imm >> kWRegSizeInBits) == 0) ||
2113            ((imm >> (kWRegSizeInBits - 1)) == 0x1ffffffff));
2114     imm &= kWRegMask;
2115   }
2116 
2117   if (shift >= 0) {
2118     // Explicit shift specified.
2119     DCHECK((shift == 0) || (shift == 16) || (shift == 32) || (shift == 48));
2120     DCHECK(rd.Is64Bits() || (shift == 0) || (shift == 16));
2121     shift /= 16;
2122   } else {
2123     // Calculate a new immediate and shift combination to encode the immediate
2124     // argument.
2125     shift = 0;
2126     if ((imm & ~0xffffUL) == 0) {
2127       // Nothing to do.
2128     } else if ((imm & ~(0xffffUL << 16)) == 0) {
2129       imm >>= 16;
2130       shift = 1;
2131     } else if ((imm & ~(0xffffUL << 32)) == 0) {
2132       DCHECK(rd.Is64Bits());
2133       imm >>= 32;
2134       shift = 2;
2135     } else if ((imm & ~(0xffffUL << 48)) == 0) {
2136       DCHECK(rd.Is64Bits());
2137       imm >>= 48;
2138       shift = 3;
2139     }
2140   }
2141 
2142   DCHECK(is_uint16(imm));
2143 
2144   Emit(SF(rd) | MoveWideImmediateFixed | mov_op |
2145        Rd(rd) | ImmMoveWide(imm) | ShiftMoveWide(shift));
2146 }
2147 
2148 
AddSub(const Register & rd,const Register & rn,const Operand & operand,FlagsUpdate S,AddSubOp op)2149 void Assembler::AddSub(const Register& rd,
2150                        const Register& rn,
2151                        const Operand& operand,
2152                        FlagsUpdate S,
2153                        AddSubOp op) {
2154   DCHECK(rd.SizeInBits() == rn.SizeInBits());
2155   DCHECK(!operand.NeedsRelocation(this));
2156   if (operand.IsImmediate()) {
2157     int64_t immediate = operand.ImmediateValue();
2158     DCHECK(IsImmAddSub(immediate));
2159     Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
2160     Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) |
2161          ImmAddSub(immediate) | dest_reg | RnSP(rn));
2162   } else if (operand.IsShiftedRegister()) {
2163     DCHECK(operand.reg().SizeInBits() == rd.SizeInBits());
2164     DCHECK(operand.shift() != ROR);
2165 
2166     // For instructions of the form:
2167     //   add/sub   wsp, <Wn>, <Wm> [, LSL #0-3 ]
2168     //   add/sub   <Wd>, wsp, <Wm> [, LSL #0-3 ]
2169     //   add/sub   wsp, wsp, <Wm> [, LSL #0-3 ]
2170     //   adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ]
2171     // or their 64-bit register equivalents, convert the operand from shifted to
2172     // extended register mode, and emit an add/sub extended instruction.
2173     if (rn.IsSP() || rd.IsSP()) {
2174       DCHECK(!(rd.IsSP() && (S == SetFlags)));
2175       DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S,
2176                                AddSubExtendedFixed | op);
2177     } else {
2178       DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op);
2179     }
2180   } else {
2181     DCHECK(operand.IsExtendedRegister());
2182     DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op);
2183   }
2184 }
2185 
2186 
AddSubWithCarry(const Register & rd,const Register & rn,const Operand & operand,FlagsUpdate S,AddSubWithCarryOp op)2187 void Assembler::AddSubWithCarry(const Register& rd,
2188                                 const Register& rn,
2189                                 const Operand& operand,
2190                                 FlagsUpdate S,
2191                                 AddSubWithCarryOp op) {
2192   DCHECK(rd.SizeInBits() == rn.SizeInBits());
2193   DCHECK(rd.SizeInBits() == operand.reg().SizeInBits());
2194   DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
2195   DCHECK(!operand.NeedsRelocation(this));
2196   Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd));
2197 }
2198 
2199 
hlt(int code)2200 void Assembler::hlt(int code) {
2201   DCHECK(is_uint16(code));
2202   Emit(HLT | ImmException(code));
2203 }
2204 
2205 
brk(int code)2206 void Assembler::brk(int code) {
2207   DCHECK(is_uint16(code));
2208   Emit(BRK | ImmException(code));
2209 }
2210 
2211 
EmitStringData(const char * string)2212 void Assembler::EmitStringData(const char* string) {
2213   size_t len = strlen(string) + 1;
2214   DCHECK(RoundUp(len, kInstructionSize) <= static_cast<size_t>(kGap));
2215   EmitData(string, len);
2216   // Pad with NULL characters until pc_ is aligned.
2217   const char pad[] = {'\0', '\0', '\0', '\0'};
2218   STATIC_ASSERT(sizeof(pad) == kInstructionSize);
2219   EmitData(pad, RoundUp(pc_offset(), kInstructionSize) - pc_offset());
2220 }
2221 
2222 
debug(const char * message,uint32_t code,Instr params)2223 void Assembler::debug(const char* message, uint32_t code, Instr params) {
2224 #ifdef USE_SIMULATOR
2225   // Don't generate simulator specific code if we are building a snapshot, which
2226   // might be run on real hardware.
2227   if (!serializer_enabled()) {
2228     // The arguments to the debug marker need to be contiguous in memory, so
2229     // make sure we don't try to emit pools.
2230     BlockPoolsScope scope(this);
2231 
2232     Label start;
2233     bind(&start);
2234 
2235     // Refer to instructions-arm64.h for a description of the marker and its
2236     // arguments.
2237     hlt(kImmExceptionIsDebug);
2238     DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugCodeOffset);
2239     dc32(code);
2240     DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugParamsOffset);
2241     dc32(params);
2242     DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugMessageOffset);
2243     EmitStringData(message);
2244     hlt(kImmExceptionIsUnreachable);
2245 
2246     return;
2247   }
2248   // Fall through if Serializer is enabled.
2249 #endif
2250 
2251   if (params & BREAK) {
2252     hlt(kImmExceptionIsDebug);
2253   }
2254 }
2255 
2256 
Logical(const Register & rd,const Register & rn,const Operand & operand,LogicalOp op)2257 void Assembler::Logical(const Register& rd,
2258                         const Register& rn,
2259                         const Operand& operand,
2260                         LogicalOp op) {
2261   DCHECK(rd.SizeInBits() == rn.SizeInBits());
2262   DCHECK(!operand.NeedsRelocation(this));
2263   if (operand.IsImmediate()) {
2264     int64_t immediate = operand.ImmediateValue();
2265     unsigned reg_size = rd.SizeInBits();
2266 
2267     DCHECK(immediate != 0);
2268     DCHECK(immediate != -1);
2269     DCHECK(rd.Is64Bits() || is_uint32(immediate));
2270 
2271     // If the operation is NOT, invert the operation and immediate.
2272     if ((op & NOT) == NOT) {
2273       op = static_cast<LogicalOp>(op & ~NOT);
2274       immediate = rd.Is64Bits() ? ~immediate : (~immediate & kWRegMask);
2275     }
2276 
2277     unsigned n, imm_s, imm_r;
2278     if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
2279       // Immediate can be encoded in the instruction.
2280       LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
2281     } else {
2282       // This case is handled in the macro assembler.
2283       UNREACHABLE();
2284     }
2285   } else {
2286     DCHECK(operand.IsShiftedRegister());
2287     DCHECK(operand.reg().SizeInBits() == rd.SizeInBits());
2288     Instr dp_op = static_cast<Instr>(op | LogicalShiftedFixed);
2289     DataProcShiftedRegister(rd, rn, operand, LeaveFlags, dp_op);
2290   }
2291 }
2292 
2293 
LogicalImmediate(const Register & rd,const Register & rn,unsigned n,unsigned imm_s,unsigned imm_r,LogicalOp op)2294 void Assembler::LogicalImmediate(const Register& rd,
2295                                  const Register& rn,
2296                                  unsigned n,
2297                                  unsigned imm_s,
2298                                  unsigned imm_r,
2299                                  LogicalOp op) {
2300   unsigned reg_size = rd.SizeInBits();
2301   Instr dest_reg = (op == ANDS) ? Rd(rd) : RdSP(rd);
2302   Emit(SF(rd) | LogicalImmediateFixed | op | BitN(n, reg_size) |
2303        ImmSetBits(imm_s, reg_size) | ImmRotate(imm_r, reg_size) | dest_reg |
2304        Rn(rn));
2305 }
2306 
2307 
ConditionalCompare(const Register & rn,const Operand & operand,StatusFlags nzcv,Condition cond,ConditionalCompareOp op)2308 void Assembler::ConditionalCompare(const Register& rn,
2309                                    const Operand& operand,
2310                                    StatusFlags nzcv,
2311                                    Condition cond,
2312                                    ConditionalCompareOp op) {
2313   Instr ccmpop;
2314   DCHECK(!operand.NeedsRelocation(this));
2315   if (operand.IsImmediate()) {
2316     int64_t immediate = operand.ImmediateValue();
2317     DCHECK(IsImmConditionalCompare(immediate));
2318     ccmpop = ConditionalCompareImmediateFixed | op | ImmCondCmp(immediate);
2319   } else {
2320     DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
2321     ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg());
2322   }
2323   Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv));
2324 }
2325 
2326 
DataProcessing1Source(const Register & rd,const Register & rn,DataProcessing1SourceOp op)2327 void Assembler::DataProcessing1Source(const Register& rd,
2328                                       const Register& rn,
2329                                       DataProcessing1SourceOp op) {
2330   DCHECK(rd.SizeInBits() == rn.SizeInBits());
2331   Emit(SF(rn) | op | Rn(rn) | Rd(rd));
2332 }
2333 
2334 
FPDataProcessing1Source(const FPRegister & fd,const FPRegister & fn,FPDataProcessing1SourceOp op)2335 void Assembler::FPDataProcessing1Source(const FPRegister& fd,
2336                                         const FPRegister& fn,
2337                                         FPDataProcessing1SourceOp op) {
2338   Emit(FPType(fn) | op | Rn(fn) | Rd(fd));
2339 }
2340 
2341 
FPDataProcessing2Source(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,FPDataProcessing2SourceOp op)2342 void Assembler::FPDataProcessing2Source(const FPRegister& fd,
2343                                         const FPRegister& fn,
2344                                         const FPRegister& fm,
2345                                         FPDataProcessing2SourceOp op) {
2346   DCHECK(fd.SizeInBits() == fn.SizeInBits());
2347   DCHECK(fd.SizeInBits() == fm.SizeInBits());
2348   Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd));
2349 }
2350 
2351 
FPDataProcessing3Source(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,const FPRegister & fa,FPDataProcessing3SourceOp op)2352 void Assembler::FPDataProcessing3Source(const FPRegister& fd,
2353                                         const FPRegister& fn,
2354                                         const FPRegister& fm,
2355                                         const FPRegister& fa,
2356                                         FPDataProcessing3SourceOp op) {
2357   DCHECK(AreSameSizeAndType(fd, fn, fm, fa));
2358   Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa));
2359 }
2360 
2361 
EmitShift(const Register & rd,const Register & rn,Shift shift,unsigned shift_amount)2362 void Assembler::EmitShift(const Register& rd,
2363                           const Register& rn,
2364                           Shift shift,
2365                           unsigned shift_amount) {
2366   switch (shift) {
2367     case LSL:
2368       lsl(rd, rn, shift_amount);
2369       break;
2370     case LSR:
2371       lsr(rd, rn, shift_amount);
2372       break;
2373     case ASR:
2374       asr(rd, rn, shift_amount);
2375       break;
2376     case ROR:
2377       ror(rd, rn, shift_amount);
2378       break;
2379     default:
2380       UNREACHABLE();
2381   }
2382 }
2383 
2384 
EmitExtendShift(const Register & rd,const Register & rn,Extend extend,unsigned left_shift)2385 void Assembler::EmitExtendShift(const Register& rd,
2386                                 const Register& rn,
2387                                 Extend extend,
2388                                 unsigned left_shift) {
2389   DCHECK(rd.SizeInBits() >= rn.SizeInBits());
2390   unsigned reg_size = rd.SizeInBits();
2391   // Use the correct size of register.
2392   Register rn_ = Register::Create(rn.code(), rd.SizeInBits());
2393   // Bits extracted are high_bit:0.
2394   unsigned high_bit = (8 << (extend & 0x3)) - 1;
2395   // Number of bits left in the result that are not introduced by the shift.
2396   unsigned non_shift_bits = (reg_size - left_shift) & (reg_size - 1);
2397 
2398   if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) {
2399     switch (extend) {
2400       case UXTB:
2401       case UXTH:
2402       case UXTW: ubfm(rd, rn_, non_shift_bits, high_bit); break;
2403       case SXTB:
2404       case SXTH:
2405       case SXTW: sbfm(rd, rn_, non_shift_bits, high_bit); break;
2406       case UXTX:
2407       case SXTX: {
2408         DCHECK(rn.SizeInBits() == kXRegSizeInBits);
2409         // Nothing to extend. Just shift.
2410         lsl(rd, rn_, left_shift);
2411         break;
2412       }
2413       default: UNREACHABLE();
2414     }
2415   } else {
2416     // No need to extend as the extended bits would be shifted away.
2417     lsl(rd, rn_, left_shift);
2418   }
2419 }
2420 
2421 
DataProcShiftedRegister(const Register & rd,const Register & rn,const Operand & operand,FlagsUpdate S,Instr op)2422 void Assembler::DataProcShiftedRegister(const Register& rd,
2423                                         const Register& rn,
2424                                         const Operand& operand,
2425                                         FlagsUpdate S,
2426                                         Instr op) {
2427   DCHECK(operand.IsShiftedRegister());
2428   DCHECK(rn.Is64Bits() || (rn.Is32Bits() && is_uint5(operand.shift_amount())));
2429   DCHECK(!operand.NeedsRelocation(this));
2430   Emit(SF(rd) | op | Flags(S) |
2431        ShiftDP(operand.shift()) | ImmDPShift(operand.shift_amount()) |
2432        Rm(operand.reg()) | Rn(rn) | Rd(rd));
2433 }
2434 
2435 
DataProcExtendedRegister(const Register & rd,const Register & rn,const Operand & operand,FlagsUpdate S,Instr op)2436 void Assembler::DataProcExtendedRegister(const Register& rd,
2437                                          const Register& rn,
2438                                          const Operand& operand,
2439                                          FlagsUpdate S,
2440                                          Instr op) {
2441   DCHECK(!operand.NeedsRelocation(this));
2442   Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
2443   Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) |
2444        ExtendMode(operand.extend()) | ImmExtendShift(operand.shift_amount()) |
2445        dest_reg | RnSP(rn));
2446 }
2447 
2448 
IsImmAddSub(int64_t immediate)2449 bool Assembler::IsImmAddSub(int64_t immediate) {
2450   return is_uint12(immediate) ||
2451          (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0));
2452 }
2453 
LoadStore(const CPURegister & rt,const MemOperand & addr,LoadStoreOp op)2454 void Assembler::LoadStore(const CPURegister& rt,
2455                           const MemOperand& addr,
2456                           LoadStoreOp op) {
2457   Instr memop = op | Rt(rt) | RnSP(addr.base());
2458   int64_t offset = addr.offset();
2459 
2460   if (addr.IsImmediateOffset()) {
2461     LSDataSize size = CalcLSDataSize(op);
2462     if (IsImmLSScaled(offset, size)) {
2463       // Use the scaled addressing mode.
2464       Emit(LoadStoreUnsignedOffsetFixed | memop |
2465            ImmLSUnsigned(offset >> size));
2466     } else if (IsImmLSUnscaled(offset)) {
2467       // Use the unscaled addressing mode.
2468       Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset));
2469     } else {
2470       // This case is handled in the macro assembler.
2471       UNREACHABLE();
2472     }
2473   } else if (addr.IsRegisterOffset()) {
2474     Extend ext = addr.extend();
2475     Shift shift = addr.shift();
2476     unsigned shift_amount = addr.shift_amount();
2477 
2478     // LSL is encoded in the option field as UXTX.
2479     if (shift == LSL) {
2480       ext = UXTX;
2481     }
2482 
2483     // Shifts are encoded in one bit, indicating a left shift by the memory
2484     // access size.
2485     DCHECK((shift_amount == 0) ||
2486            (shift_amount == static_cast<unsigned>(CalcLSDataSize(op))));
2487     Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) |
2488          ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0));
2489   } else {
2490     // Pre-index and post-index modes.
2491     DCHECK(!rt.Is(addr.base()));
2492     if (IsImmLSUnscaled(offset)) {
2493       if (addr.IsPreIndex()) {
2494         Emit(LoadStorePreIndexFixed | memop | ImmLS(offset));
2495       } else {
2496         DCHECK(addr.IsPostIndex());
2497         Emit(LoadStorePostIndexFixed | memop | ImmLS(offset));
2498       }
2499     } else {
2500       // This case is handled in the macro assembler.
2501       UNREACHABLE();
2502     }
2503   }
2504 }
2505 
2506 
IsImmLSUnscaled(int64_t offset)2507 bool Assembler::IsImmLSUnscaled(int64_t offset) {
2508   return is_int9(offset);
2509 }
2510 
2511 
IsImmLSScaled(int64_t offset,LSDataSize size)2512 bool Assembler::IsImmLSScaled(int64_t offset, LSDataSize size) {
2513   bool offset_is_size_multiple = (((offset >> size) << size) == offset);
2514   return offset_is_size_multiple && is_uint12(offset >> size);
2515 }
2516 
2517 
IsImmLSPair(int64_t offset,LSDataSize size)2518 bool Assembler::IsImmLSPair(int64_t offset, LSDataSize size) {
2519   bool offset_is_size_multiple = (((offset >> size) << size) == offset);
2520   return offset_is_size_multiple && is_int7(offset >> size);
2521 }
2522 
2523 
2524 // Test if a given value can be encoded in the immediate field of a logical
2525 // instruction.
2526 // If it can be encoded, the function returns true, and values pointed to by n,
2527 // imm_s and imm_r are updated with immediates encoded in the format required
2528 // by the corresponding fields in the logical instruction.
2529 // If it can not be encoded, the function returns false, and the values pointed
2530 // to by n, imm_s and imm_r are undefined.
IsImmLogical(uint64_t value,unsigned width,unsigned * n,unsigned * imm_s,unsigned * imm_r)2531 bool Assembler::IsImmLogical(uint64_t value,
2532                              unsigned width,
2533                              unsigned* n,
2534                              unsigned* imm_s,
2535                              unsigned* imm_r) {
2536   DCHECK((n != NULL) && (imm_s != NULL) && (imm_r != NULL));
2537   DCHECK((width == kWRegSizeInBits) || (width == kXRegSizeInBits));
2538 
2539   bool negate = false;
2540 
2541   // Logical immediates are encoded using parameters n, imm_s and imm_r using
2542   // the following table:
2543   //
2544   //    N   imms    immr    size        S             R
2545   //    1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
2546   //    0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
2547   //    0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
2548   //    0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
2549   //    0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
2550   //    0  11110s  xxxxxr     2    UInt(s)       UInt(r)
2551   // (s bits must not be all set)
2552   //
2553   // A pattern is constructed of size bits, where the least significant S+1 bits
2554   // are set. The pattern is rotated right by R, and repeated across a 32 or
2555   // 64-bit value, depending on destination register width.
2556   //
2557   // Put another way: the basic format of a logical immediate is a single
2558   // contiguous stretch of 1 bits, repeated across the whole word at intervals
2559   // given by a power of 2. To identify them quickly, we first locate the
2560   // lowest stretch of 1 bits, then the next 1 bit above that; that combination
2561   // is different for every logical immediate, so it gives us all the
2562   // information we need to identify the only logical immediate that our input
2563   // could be, and then we simply check if that's the value we actually have.
2564   //
2565   // (The rotation parameter does give the possibility of the stretch of 1 bits
2566   // going 'round the end' of the word. To deal with that, we observe that in
2567   // any situation where that happens the bitwise NOT of the value is also a
2568   // valid logical immediate. So we simply invert the input whenever its low bit
2569   // is set, and then we know that the rotated case can't arise.)
2570 
2571   if (value & 1) {
2572     // If the low bit is 1, negate the value, and set a flag to remember that we
2573     // did (so that we can adjust the return values appropriately).
2574     negate = true;
2575     value = ~value;
2576   }
2577 
2578   if (width == kWRegSizeInBits) {
2579     // To handle 32-bit logical immediates, the very easiest thing is to repeat
2580     // the input value twice to make a 64-bit word. The correct encoding of that
2581     // as a logical immediate will also be the correct encoding of the 32-bit
2582     // value.
2583 
2584     // The most-significant 32 bits may not be zero (ie. negate is true) so
2585     // shift the value left before duplicating it.
2586     value <<= kWRegSizeInBits;
2587     value |= value >> kWRegSizeInBits;
2588   }
2589 
2590   // The basic analysis idea: imagine our input word looks like this.
2591   //
2592   //    0011111000111110001111100011111000111110001111100011111000111110
2593   //                                                          c  b    a
2594   //                                                          |<--d-->|
2595   //
2596   // We find the lowest set bit (as an actual power-of-2 value, not its index)
2597   // and call it a. Then we add a to our original number, which wipes out the
2598   // bottommost stretch of set bits and replaces it with a 1 carried into the
2599   // next zero bit. Then we look for the new lowest set bit, which is in
2600   // position b, and subtract it, so now our number is just like the original
2601   // but with the lowest stretch of set bits completely gone. Now we find the
2602   // lowest set bit again, which is position c in the diagram above. Then we'll
2603   // measure the distance d between bit positions a and c (using CLZ), and that
2604   // tells us that the only valid logical immediate that could possibly be equal
2605   // to this number is the one in which a stretch of bits running from a to just
2606   // below b is replicated every d bits.
2607   uint64_t a = LargestPowerOf2Divisor(value);
2608   uint64_t value_plus_a = value + a;
2609   uint64_t b = LargestPowerOf2Divisor(value_plus_a);
2610   uint64_t value_plus_a_minus_b = value_plus_a - b;
2611   uint64_t c = LargestPowerOf2Divisor(value_plus_a_minus_b);
2612 
2613   int d, clz_a, out_n;
2614   uint64_t mask;
2615 
2616   if (c != 0) {
2617     // The general case, in which there is more than one stretch of set bits.
2618     // Compute the repeat distance d, and set up a bitmask covering the basic
2619     // unit of repetition (i.e. a word with the bottom d bits set). Also, in all
2620     // of these cases the N bit of the output will be zero.
2621     clz_a = CountLeadingZeros(a, kXRegSizeInBits);
2622     int clz_c = CountLeadingZeros(c, kXRegSizeInBits);
2623     d = clz_a - clz_c;
2624     mask = ((V8_UINT64_C(1) << d) - 1);
2625     out_n = 0;
2626   } else {
2627     // Handle degenerate cases.
2628     //
2629     // If any of those 'find lowest set bit' operations didn't find a set bit at
2630     // all, then the word will have been zero thereafter, so in particular the
2631     // last lowest_set_bit operation will have returned zero. So we can test for
2632     // all the special case conditions in one go by seeing if c is zero.
2633     if (a == 0) {
2634       // The input was zero (or all 1 bits, which will come to here too after we
2635       // inverted it at the start of the function), for which we just return
2636       // false.
2637       return false;
2638     } else {
2639       // Otherwise, if c was zero but a was not, then there's just one stretch
2640       // of set bits in our word, meaning that we have the trivial case of
2641       // d == 64 and only one 'repetition'. Set up all the same variables as in
2642       // the general case above, and set the N bit in the output.
2643       clz_a = CountLeadingZeros(a, kXRegSizeInBits);
2644       d = 64;
2645       mask = ~V8_UINT64_C(0);
2646       out_n = 1;
2647     }
2648   }
2649 
2650   // If the repeat period d is not a power of two, it can't be encoded.
2651   if (!IS_POWER_OF_TWO(d)) {
2652     return false;
2653   }
2654 
2655   if (((b - a) & ~mask) != 0) {
2656     // If the bit stretch (b - a) does not fit within the mask derived from the
2657     // repeat period, then fail.
2658     return false;
2659   }
2660 
2661   // The only possible option is b - a repeated every d bits. Now we're going to
2662   // actually construct the valid logical immediate derived from that
2663   // specification, and see if it equals our original input.
2664   //
2665   // To repeat a value every d bits, we multiply it by a number of the form
2666   // (1 + 2^d + 2^(2d) + ...), i.e. 0x0001000100010001 or similar. These can
2667   // be derived using a table lookup on CLZ(d).
2668   static const uint64_t multipliers[] = {
2669     0x0000000000000001UL,
2670     0x0000000100000001UL,
2671     0x0001000100010001UL,
2672     0x0101010101010101UL,
2673     0x1111111111111111UL,
2674     0x5555555555555555UL,
2675   };
2676   int multiplier_idx = CountLeadingZeros(d, kXRegSizeInBits) - 57;
2677   // Ensure that the index to the multipliers array is within bounds.
2678   DCHECK((multiplier_idx >= 0) &&
2679          (static_cast<size_t>(multiplier_idx) < arraysize(multipliers)));
2680   uint64_t multiplier = multipliers[multiplier_idx];
2681   uint64_t candidate = (b - a) * multiplier;
2682 
2683   if (value != candidate) {
2684     // The candidate pattern doesn't match our input value, so fail.
2685     return false;
2686   }
2687 
2688   // We have a match! This is a valid logical immediate, so now we have to
2689   // construct the bits and pieces of the instruction encoding that generates
2690   // it.
2691 
2692   // Count the set bits in our basic stretch. The special case of clz(0) == -1
2693   // makes the answer come out right for stretches that reach the very top of
2694   // the word (e.g. numbers like 0xffffc00000000000).
2695   int clz_b = (b == 0) ? -1 : CountLeadingZeros(b, kXRegSizeInBits);
2696   int s = clz_a - clz_b;
2697 
2698   // Decide how many bits to rotate right by, to put the low bit of that basic
2699   // stretch in position a.
2700   int r;
2701   if (negate) {
2702     // If we inverted the input right at the start of this function, here's
2703     // where we compensate: the number of set bits becomes the number of clear
2704     // bits, and the rotation count is based on position b rather than position
2705     // a (since b is the location of the 'lowest' 1 bit after inversion).
2706     s = d - s;
2707     r = (clz_b + 1) & (d - 1);
2708   } else {
2709     r = (clz_a + 1) & (d - 1);
2710   }
2711 
2712   // Now we're done, except for having to encode the S output in such a way that
2713   // it gives both the number of set bits and the length of the repeated
2714   // segment. The s field is encoded like this:
2715   //
2716   //     imms    size        S
2717   //    ssssss    64    UInt(ssssss)
2718   //    0sssss    32    UInt(sssss)
2719   //    10ssss    16    UInt(ssss)
2720   //    110sss     8    UInt(sss)
2721   //    1110ss     4    UInt(ss)
2722   //    11110s     2    UInt(s)
2723   //
2724   // So we 'or' (-d << 1) with our computed s to form imms.
2725   *n = out_n;
2726   *imm_s = ((-d << 1) | (s - 1)) & 0x3f;
2727   *imm_r = r;
2728 
2729   return true;
2730 }
2731 
2732 
IsImmConditionalCompare(int64_t immediate)2733 bool Assembler::IsImmConditionalCompare(int64_t immediate) {
2734   return is_uint5(immediate);
2735 }
2736 
2737 
IsImmFP32(float imm)2738 bool Assembler::IsImmFP32(float imm) {
2739   // Valid values will have the form:
2740   // aBbb.bbbc.defg.h000.0000.0000.0000.0000
2741   uint32_t bits = float_to_rawbits(imm);
2742   // bits[19..0] are cleared.
2743   if ((bits & 0x7ffff) != 0) {
2744     return false;
2745   }
2746 
2747   // bits[29..25] are all set or all cleared.
2748   uint32_t b_pattern = (bits >> 16) & 0x3e00;
2749   if (b_pattern != 0 && b_pattern != 0x3e00) {
2750     return false;
2751   }
2752 
2753   // bit[30] and bit[29] are opposite.
2754   if (((bits ^ (bits << 1)) & 0x40000000) == 0) {
2755     return false;
2756   }
2757 
2758   return true;
2759 }
2760 
2761 
IsImmFP64(double imm)2762 bool Assembler::IsImmFP64(double imm) {
2763   // Valid values will have the form:
2764   // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2765   // 0000.0000.0000.0000.0000.0000.0000.0000
2766   uint64_t bits = double_to_rawbits(imm);
2767   // bits[47..0] are cleared.
2768   if ((bits & 0xffffffffffffL) != 0) {
2769     return false;
2770   }
2771 
2772   // bits[61..54] are all set or all cleared.
2773   uint32_t b_pattern = (bits >> 48) & 0x3fc0;
2774   if (b_pattern != 0 && b_pattern != 0x3fc0) {
2775     return false;
2776   }
2777 
2778   // bit[62] and bit[61] are opposite.
2779   if (((bits ^ (bits << 1)) & 0x4000000000000000L) == 0) {
2780     return false;
2781   }
2782 
2783   return true;
2784 }
2785 
2786 
GrowBuffer()2787 void Assembler::GrowBuffer() {
2788   if (!own_buffer_) FATAL("external code buffer is too small");
2789 
2790   // Compute new buffer size.
2791   CodeDesc desc;  // the new buffer
2792   if (buffer_size_ < 1 * MB) {
2793     desc.buffer_size = 2 * buffer_size_;
2794   } else {
2795     desc.buffer_size = buffer_size_ + 1 * MB;
2796   }
2797   CHECK_GT(desc.buffer_size, 0);  // No overflow.
2798 
2799   byte* buffer = reinterpret_cast<byte*>(buffer_);
2800 
2801   // Set up new buffer.
2802   desc.buffer = NewArray<byte>(desc.buffer_size);
2803 
2804   desc.instr_size = pc_offset();
2805   desc.reloc_size = (buffer + buffer_size_) - reloc_info_writer.pos();
2806 
2807   // Copy the data.
2808   intptr_t pc_delta = desc.buffer - buffer;
2809   intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
2810                       (buffer + buffer_size_);
2811   memmove(desc.buffer, buffer, desc.instr_size);
2812   memmove(reloc_info_writer.pos() + rc_delta,
2813           reloc_info_writer.pos(), desc.reloc_size);
2814 
2815   // Switch buffers.
2816   DeleteArray(buffer_);
2817   buffer_ = desc.buffer;
2818   buffer_size_ = desc.buffer_size;
2819   pc_ = reinterpret_cast<byte*>(pc_) + pc_delta;
2820   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2821                                reloc_info_writer.last_pc() + pc_delta);
2822 
2823   // None of our relocation types are pc relative pointing outside the code
2824   // buffer nor pc absolute pointing inside the code buffer, so there is no need
2825   // to relocate any emitted relocation entries.
2826 
2827   // Pending relocation entries are also relative, no need to relocate.
2828 }
2829 
2830 
RecordRelocInfo(RelocInfo::Mode rmode,intptr_t data)2831 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2832   // We do not try to reuse pool constants.
2833   RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL);
2834   if (((rmode >= RelocInfo::JS_RETURN) &&
2835        (rmode <= RelocInfo::DEBUG_BREAK_SLOT)) ||
2836       (rmode == RelocInfo::CONST_POOL) ||
2837       (rmode == RelocInfo::VENEER_POOL)) {
2838     // Adjust code for new modes.
2839     DCHECK(RelocInfo::IsDebugBreakSlot(rmode)
2840            || RelocInfo::IsJSReturn(rmode)
2841            || RelocInfo::IsComment(rmode)
2842            || RelocInfo::IsPosition(rmode)
2843            || RelocInfo::IsConstPool(rmode)
2844            || RelocInfo::IsVeneerPool(rmode));
2845     // These modes do not need an entry in the constant pool.
2846   } else {
2847     constpool_.RecordEntry(data, rmode);
2848     // Make sure the constant pool is not emitted in place of the next
2849     // instruction for which we just recorded relocation info.
2850     BlockConstPoolFor(1);
2851   }
2852 
2853   if (!RelocInfo::IsNone(rmode)) {
2854     // Don't record external references unless the heap will be serialized.
2855     if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
2856         !serializer_enabled() && !emit_debug_code()) {
2857       return;
2858     }
2859     DCHECK(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
2860     if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
2861       RelocInfo reloc_info_with_ast_id(
2862           reinterpret_cast<byte*>(pc_), rmode, RecordedAstId().ToInt(), NULL);
2863       ClearRecordedAstId();
2864       reloc_info_writer.Write(&reloc_info_with_ast_id);
2865     } else {
2866       reloc_info_writer.Write(&rinfo);
2867     }
2868   }
2869 }
2870 
2871 
BlockConstPoolFor(int instructions)2872 void Assembler::BlockConstPoolFor(int instructions) {
2873   int pc_limit = pc_offset() + instructions * kInstructionSize;
2874   if (no_const_pool_before_ < pc_limit) {
2875     no_const_pool_before_ = pc_limit;
2876     // Make sure the pool won't be blocked for too long.
2877     DCHECK(pc_limit < constpool_.MaxPcOffset());
2878   }
2879 
2880   if (next_constant_pool_check_ < no_const_pool_before_) {
2881     next_constant_pool_check_ = no_const_pool_before_;
2882   }
2883 }
2884 
2885 
CheckConstPool(bool force_emit,bool require_jump)2886 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
2887   // Some short sequence of instruction mustn't be broken up by constant pool
2888   // emission, such sequences are protected by calls to BlockConstPoolFor and
2889   // BlockConstPoolScope.
2890   if (is_const_pool_blocked()) {
2891     // Something is wrong if emission is forced and blocked at the same time.
2892     DCHECK(!force_emit);
2893     return;
2894   }
2895 
2896   // There is nothing to do if there are no pending constant pool entries.
2897   if (constpool_.IsEmpty())  {
2898     // Calculate the offset of the next check.
2899     SetNextConstPoolCheckIn(kCheckConstPoolInterval);
2900     return;
2901   }
2902 
2903   // We emit a constant pool when:
2904   //  * requested to do so by parameter force_emit (e.g. after each function).
2905   //  * the distance to the first instruction accessing the constant pool is
2906   //    kApproxMaxDistToConstPool or more.
2907   //  * the number of entries in the pool is kApproxMaxPoolEntryCount or more.
2908   int dist = constpool_.DistanceToFirstUse();
2909   int count = constpool_.EntryCount();
2910   if (!force_emit &&
2911       (dist < kApproxMaxDistToConstPool) &&
2912       (count < kApproxMaxPoolEntryCount)) {
2913     return;
2914   }
2915 
2916 
2917   // Emit veneers for branches that would go out of range during emission of the
2918   // constant pool.
2919   int worst_case_size = constpool_.WorstCaseSize();
2920   CheckVeneerPool(false, require_jump,
2921                   kVeneerDistanceMargin + worst_case_size);
2922 
2923   // Check that the code buffer is large enough before emitting the constant
2924   // pool (this includes the gap to the relocation information).
2925   int needed_space = worst_case_size + kGap + 1 * kInstructionSize;
2926   while (buffer_space() <= needed_space) {
2927     GrowBuffer();
2928   }
2929 
2930   Label size_check;
2931   bind(&size_check);
2932   constpool_.Emit(require_jump);
2933   DCHECK(SizeOfCodeGeneratedSince(&size_check) <=
2934          static_cast<unsigned>(worst_case_size));
2935 
2936   // Since a constant pool was just emitted, move the check offset forward by
2937   // the standard interval.
2938   SetNextConstPoolCheckIn(kCheckConstPoolInterval);
2939 }
2940 
2941 
ShouldEmitVeneer(int max_reachable_pc,int margin)2942 bool Assembler::ShouldEmitVeneer(int max_reachable_pc, int margin) {
2943   // Account for the branch around the veneers and the guard.
2944   int protection_offset = 2 * kInstructionSize;
2945   return pc_offset() > max_reachable_pc - margin - protection_offset -
2946     static_cast<int>(unresolved_branches_.size() * kMaxVeneerCodeSize);
2947 }
2948 
2949 
RecordVeneerPool(int location_offset,int size)2950 void Assembler::RecordVeneerPool(int location_offset, int size) {
2951   RelocInfo rinfo(buffer_ + location_offset,
2952                   RelocInfo::VENEER_POOL, static_cast<intptr_t>(size),
2953                   NULL);
2954   reloc_info_writer.Write(&rinfo);
2955 }
2956 
2957 
EmitVeneers(bool force_emit,bool need_protection,int margin)2958 void Assembler::EmitVeneers(bool force_emit, bool need_protection, int margin) {
2959   BlockPoolsScope scope(this);
2960   RecordComment("[ Veneers");
2961 
2962   // The exact size of the veneer pool must be recorded (see the comment at the
2963   // declaration site of RecordConstPool()), but computing the number of
2964   // veneers that will be generated is not obvious. So instead we remember the
2965   // current position and will record the size after the pool has been
2966   // generated.
2967   Label size_check;
2968   bind(&size_check);
2969   int veneer_pool_relocinfo_loc = pc_offset();
2970 
2971   Label end;
2972   if (need_protection) {
2973     b(&end);
2974   }
2975 
2976   EmitVeneersGuard();
2977 
2978   Label veneer_size_check;
2979 
2980   std::multimap<int, FarBranchInfo>::iterator it, it_to_delete;
2981 
2982   it = unresolved_branches_.begin();
2983   while (it != unresolved_branches_.end()) {
2984     if (force_emit || ShouldEmitVeneer(it->first, margin)) {
2985       Instruction* branch = InstructionAt(it->second.pc_offset_);
2986       Label* label = it->second.label_;
2987 
2988 #ifdef DEBUG
2989       bind(&veneer_size_check);
2990 #endif
2991       // Patch the branch to point to the current position, and emit a branch
2992       // to the label.
2993       Instruction* veneer = reinterpret_cast<Instruction*>(pc_);
2994       RemoveBranchFromLabelLinkChain(branch, label, veneer);
2995       branch->SetImmPCOffsetTarget(veneer);
2996       b(label);
2997 #ifdef DEBUG
2998       DCHECK(SizeOfCodeGeneratedSince(&veneer_size_check) <=
2999              static_cast<uint64_t>(kMaxVeneerCodeSize));
3000       veneer_size_check.Unuse();
3001 #endif
3002 
3003       it_to_delete = it++;
3004       unresolved_branches_.erase(it_to_delete);
3005     } else {
3006       ++it;
3007     }
3008   }
3009 
3010   // Record the veneer pool size.
3011   int pool_size = SizeOfCodeGeneratedSince(&size_check);
3012   RecordVeneerPool(veneer_pool_relocinfo_loc, pool_size);
3013 
3014   if (unresolved_branches_.empty()) {
3015     next_veneer_pool_check_ = kMaxInt;
3016   } else {
3017     next_veneer_pool_check_ =
3018       unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
3019   }
3020 
3021   bind(&end);
3022 
3023   RecordComment("]");
3024 }
3025 
3026 
CheckVeneerPool(bool force_emit,bool require_jump,int margin)3027 void Assembler::CheckVeneerPool(bool force_emit, bool require_jump,
3028                                 int margin) {
3029   // There is nothing to do if there are no pending veneer pool entries.
3030   if (unresolved_branches_.empty())  {
3031     DCHECK(next_veneer_pool_check_ == kMaxInt);
3032     return;
3033   }
3034 
3035   DCHECK(pc_offset() < unresolved_branches_first_limit());
3036 
3037   // Some short sequence of instruction mustn't be broken up by veneer pool
3038   // emission, such sequences are protected by calls to BlockVeneerPoolFor and
3039   // BlockVeneerPoolScope.
3040   if (is_veneer_pool_blocked()) {
3041     DCHECK(!force_emit);
3042     return;
3043   }
3044 
3045   if (!require_jump) {
3046     // Prefer emitting veneers protected by an existing instruction.
3047     margin *= kVeneerNoProtectionFactor;
3048   }
3049   if (force_emit || ShouldEmitVeneers(margin)) {
3050     EmitVeneers(force_emit, require_jump, margin);
3051   } else {
3052     next_veneer_pool_check_ =
3053       unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
3054   }
3055 }
3056 
3057 
RecordComment(const char * msg)3058 void Assembler::RecordComment(const char* msg) {
3059   if (FLAG_code_comments) {
3060     CheckBuffer();
3061     RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
3062   }
3063 }
3064 
3065 
buffer_space() const3066 int Assembler::buffer_space() const {
3067   return reloc_info_writer.pos() - reinterpret_cast<byte*>(pc_);
3068 }
3069 
3070 
RecordJSReturn()3071 void Assembler::RecordJSReturn() {
3072   positions_recorder()->WriteRecordedPositions();
3073   CheckBuffer();
3074   RecordRelocInfo(RelocInfo::JS_RETURN);
3075 }
3076 
3077 
RecordDebugBreakSlot()3078 void Assembler::RecordDebugBreakSlot() {
3079   positions_recorder()->WriteRecordedPositions();
3080   CheckBuffer();
3081   RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
3082 }
3083 
3084 
RecordConstPool(int size)3085 void Assembler::RecordConstPool(int size) {
3086   // We only need this for debugger support, to correctly compute offsets in the
3087   // code.
3088   RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
3089 }
3090 
3091 
NewConstantPool(Isolate * isolate)3092 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
3093   // No out-of-line constant pool support.
3094   DCHECK(!FLAG_enable_ool_constant_pool);
3095   return isolate->factory()->empty_constant_pool_array();
3096 }
3097 
3098 
PopulateConstantPool(ConstantPoolArray * constant_pool)3099 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
3100   // No out-of-line constant pool support.
3101   DCHECK(!FLAG_enable_ool_constant_pool);
3102   return;
3103 }
3104 
3105 
PatchAdrFar(int64_t target_offset)3106 void PatchingAssembler::PatchAdrFar(int64_t target_offset) {
3107   // The code at the current instruction should be:
3108   //   adr  rd, 0
3109   //   nop  (adr_far)
3110   //   nop  (adr_far)
3111   //   movz scratch, 0
3112 
3113   // Verify the expected code.
3114   Instruction* expected_adr = InstructionAt(0);
3115   CHECK(expected_adr->IsAdr() && (expected_adr->ImmPCRel() == 0));
3116   int rd_code = expected_adr->Rd();
3117   for (int i = 0; i < kAdrFarPatchableNNops; ++i) {
3118     CHECK(InstructionAt((i + 1) * kInstructionSize)->IsNop(ADR_FAR_NOP));
3119   }
3120   Instruction* expected_movz =
3121       InstructionAt((kAdrFarPatchableNInstrs - 1) * kInstructionSize);
3122   CHECK(expected_movz->IsMovz() &&
3123         (expected_movz->ImmMoveWide() == 0) &&
3124         (expected_movz->ShiftMoveWide() == 0));
3125   int scratch_code = expected_movz->Rd();
3126 
3127   // Patch to load the correct address.
3128   Register rd = Register::XRegFromCode(rd_code);
3129   Register scratch = Register::XRegFromCode(scratch_code);
3130   // Addresses are only 48 bits.
3131   adr(rd, target_offset & 0xFFFF);
3132   movz(scratch, (target_offset >> 16) & 0xFFFF, 16);
3133   movk(scratch, (target_offset >> 32) & 0xFFFF, 32);
3134   DCHECK((target_offset >> 48) == 0);
3135   add(rd, rd, scratch);
3136 }
3137 
3138 
3139 } }  // namespace v8::internal
3140 
3141 #endif  // V8_TARGET_ARCH_ARM64
3142