• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #if V8_TARGET_ARCH_ARM64
30 
31 #include "src/codegen/arm64/assembler-arm64.h"
32 
33 #include "src/base/bits.h"
34 #include "src/base/cpu.h"
35 #include "src/codegen/arm64/assembler-arm64-inl.h"
36 #include "src/codegen/register-configuration.h"
37 #include "src/codegen/safepoint-table.h"
38 #include "src/codegen/string-constants.h"
39 #include "src/execution/frame-constants.h"
40 
41 namespace v8 {
42 namespace internal {
43 
44 namespace {
45 
46 #ifdef USE_SIMULATOR
SimulatorFeaturesFromCommandLine()47 static unsigned SimulatorFeaturesFromCommandLine() {
48   if (strcmp(FLAG_sim_arm64_optional_features, "none") == 0) {
49     return 0;
50   }
51   if (strcmp(FLAG_sim_arm64_optional_features, "all") == 0) {
52     return (1u << NUMBER_OF_CPU_FEATURES) - 1;
53   }
54   fprintf(
55       stderr,
56       "Error: unrecognised value for --sim-arm64-optional-features ('%s').\n",
57       FLAG_sim_arm64_optional_features);
58   fprintf(stderr,
59           "Supported values are:  none\n"
60           "                       all\n");
61   FATAL("sim-arm64-optional-features");
62 }
63 #endif  // USE_SIMULATOR
64 
CpuFeaturesFromCompiler()65 static constexpr unsigned CpuFeaturesFromCompiler() {
66   unsigned features = 0;
67 #if defined(__ARM_FEATURE_JCVT)
68   features |= 1u << JSCVT;
69 #endif
70   return features;
71 }
72 
73 }  // namespace
74 
75 // -----------------------------------------------------------------------------
76 // CpuFeatures implementation.
77 
ProbeImpl(bool cross_compile)78 void CpuFeatures::ProbeImpl(bool cross_compile) {
79   // Only use statically determined features for cross compile (snapshot).
80   if (cross_compile) {
81     supported_ |= CpuFeaturesFromCompiler();
82     return;
83   }
84 
85   // We used to probe for coherent cache support, but on older CPUs it
86   // causes crashes (crbug.com/524337), and newer CPUs don't even have
87   // the feature any more.
88 
89 #ifdef USE_SIMULATOR
90   supported_ |= SimulatorFeaturesFromCommandLine();
91 #else
92   // Probe for additional features at runtime.
93   base::CPU cpu;
94   unsigned runtime = 0;
95   if (cpu.has_jscvt()) {
96     runtime |= 1u << JSCVT;
97   }
98 
99   // Use the best of the features found by CPU detection and those inferred from
100   // the build system.
101   supported_ |= CpuFeaturesFromCompiler();
102   supported_ |= runtime;
103 #endif  // USE_SIMULATOR
104 }
105 
PrintTarget()106 void CpuFeatures::PrintTarget() {}
PrintFeatures()107 void CpuFeatures::PrintFeatures() {}
108 
109 // -----------------------------------------------------------------------------
110 // CPURegList utilities.
111 
PopLowestIndex()112 CPURegister CPURegList::PopLowestIndex() {
113   if (IsEmpty()) {
114     return NoCPUReg;
115   }
116   int index = base::bits::CountTrailingZeros(list_);
117   DCHECK((1LL << index) & list_);
118   Remove(index);
119   return CPURegister::Create(index, size_, type_);
120 }
121 
PopHighestIndex()122 CPURegister CPURegList::PopHighestIndex() {
123   if (IsEmpty()) {
124     return NoCPUReg;
125   }
126   int index = CountLeadingZeros(list_, kRegListSizeInBits);
127   index = kRegListSizeInBits - 1 - index;
128   DCHECK((1LL << index) & list_);
129   Remove(index);
130   return CPURegister::Create(index, size_, type_);
131 }
132 
Align()133 void CPURegList::Align() {
134   // Use padreg, if necessary, to maintain stack alignment.
135   if (Count() % 2 != 0) {
136     if (IncludesAliasOf(padreg)) {
137       Remove(padreg);
138     } else {
139       Combine(padreg);
140     }
141   }
142 
143   DCHECK_EQ(Count() % 2, 0);
144 }
145 
GetCalleeSaved(int size)146 CPURegList CPURegList::GetCalleeSaved(int size) {
147   return CPURegList(CPURegister::kRegister, size, 19, 28);
148 }
149 
GetCalleeSavedV(int size)150 CPURegList CPURegList::GetCalleeSavedV(int size) {
151   return CPURegList(CPURegister::kVRegister, size, 8, 15);
152 }
153 
GetCallerSaved(int size)154 CPURegList CPURegList::GetCallerSaved(int size) {
155   // x18 is the platform register and is reserved for the use of platform ABIs.
156   // Registers x0-x17 are caller-saved.
157   CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 17);
158   return list;
159 }
160 
GetCallerSavedV(int size)161 CPURegList CPURegList::GetCallerSavedV(int size) {
162   // Registers d0-d7 and d16-d31 are caller-saved.
163   CPURegList list = CPURegList(CPURegister::kVRegister, size, 0, 7);
164   list.Combine(CPURegList(CPURegister::kVRegister, size, 16, 31));
165   return list;
166 }
167 
168 // -----------------------------------------------------------------------------
169 // Implementation of RelocInfo
170 
171 const int RelocInfo::kApplyMask =
172     RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
173     RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
174     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE);
175 
IsCodedSpecially()176 bool RelocInfo::IsCodedSpecially() {
177   // The deserializer needs to know whether a pointer is specially coded. Being
178   // specially coded on ARM64 means that it is an immediate branch.
179   Instruction* instr = reinterpret_cast<Instruction*>(pc_);
180   if (instr->IsLdrLiteralX()) {
181     return false;
182   } else {
183     DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
184     return true;
185   }
186 }
187 
IsInConstantPool()188 bool RelocInfo::IsInConstantPool() {
189   Instruction* instr = reinterpret_cast<Instruction*>(pc_);
190   DCHECK_IMPLIES(instr->IsLdrLiteralW(), COMPRESS_POINTERS_BOOL);
191   return instr->IsLdrLiteralX() ||
192          (COMPRESS_POINTERS_BOOL && instr->IsLdrLiteralW());
193 }
194 
wasm_call_tag() const195 uint32_t RelocInfo::wasm_call_tag() const {
196   DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
197   Instruction* instr = reinterpret_cast<Instruction*>(pc_);
198   if (instr->IsLdrLiteralX()) {
199     return static_cast<uint32_t>(
200         Memory<Address>(Assembler::target_pointer_address_at(pc_)));
201   } else {
202     DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
203     return static_cast<uint32_t>(instr->ImmPCOffset() / kInstrSize);
204   }
205 }
206 
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)207 bool AreAliased(const CPURegister& reg1, const CPURegister& reg2,
208                 const CPURegister& reg3, const CPURegister& reg4,
209                 const CPURegister& reg5, const CPURegister& reg6,
210                 const CPURegister& reg7, const CPURegister& reg8) {
211   int number_of_valid_regs = 0;
212   int number_of_valid_fpregs = 0;
213 
214   RegList unique_regs = 0;
215   RegList unique_fpregs = 0;
216 
217   const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};
218 
219   for (unsigned i = 0; i < arraysize(regs); i++) {
220     if (regs[i].IsRegister()) {
221       number_of_valid_regs++;
222       unique_regs |= regs[i].bit();
223     } else if (regs[i].IsVRegister()) {
224       number_of_valid_fpregs++;
225       unique_fpregs |= regs[i].bit();
226     } else {
227       DCHECK(!regs[i].is_valid());
228     }
229   }
230 
231   int number_of_unique_regs =
232       CountSetBits(unique_regs, sizeof(unique_regs) * kBitsPerByte);
233   int number_of_unique_fpregs =
234       CountSetBits(unique_fpregs, sizeof(unique_fpregs) * kBitsPerByte);
235 
236   DCHECK(number_of_valid_regs >= number_of_unique_regs);
237   DCHECK(number_of_valid_fpregs >= number_of_unique_fpregs);
238 
239   return (number_of_valid_regs != number_of_unique_regs) ||
240          (number_of_valid_fpregs != number_of_unique_fpregs);
241 }
242 
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)243 bool AreSameSizeAndType(const CPURegister& reg1, const CPURegister& reg2,
244                         const CPURegister& reg3, const CPURegister& reg4,
245                         const CPURegister& reg5, const CPURegister& reg6,
246                         const CPURegister& reg7, const CPURegister& reg8) {
247   DCHECK(reg1.is_valid());
248   bool match = true;
249   match &= !reg2.is_valid() || reg2.IsSameSizeAndType(reg1);
250   match &= !reg3.is_valid() || reg3.IsSameSizeAndType(reg1);
251   match &= !reg4.is_valid() || reg4.IsSameSizeAndType(reg1);
252   match &= !reg5.is_valid() || reg5.IsSameSizeAndType(reg1);
253   match &= !reg6.is_valid() || reg6.IsSameSizeAndType(reg1);
254   match &= !reg7.is_valid() || reg7.IsSameSizeAndType(reg1);
255   match &= !reg8.is_valid() || reg8.IsSameSizeAndType(reg1);
256   return match;
257 }
258 
AreSameFormat(const VRegister & reg1,const VRegister & reg2,const VRegister & reg3,const VRegister & reg4)259 bool AreSameFormat(const VRegister& reg1, const VRegister& reg2,
260                    const VRegister& reg3, const VRegister& reg4) {
261   DCHECK(reg1.is_valid());
262   return (!reg2.is_valid() || reg2.IsSameFormat(reg1)) &&
263          (!reg3.is_valid() || reg3.IsSameFormat(reg1)) &&
264          (!reg4.is_valid() || reg4.IsSameFormat(reg1));
265 }
266 
AreConsecutive(const VRegister & reg1,const VRegister & reg2,const VRegister & reg3,const VRegister & reg4)267 bool AreConsecutive(const VRegister& reg1, const VRegister& reg2,
268                     const VRegister& reg3, const VRegister& reg4) {
269   DCHECK(reg1.is_valid());
270   if (!reg2.is_valid()) {
271     DCHECK(!reg3.is_valid() && !reg4.is_valid());
272     return true;
273   } else if (reg2.code() != ((reg1.code() + 1) % kNumberOfVRegisters)) {
274     return false;
275   }
276 
277   if (!reg3.is_valid()) {
278     DCHECK(!reg4.is_valid());
279     return true;
280   } else if (reg3.code() != ((reg2.code() + 1) % kNumberOfVRegisters)) {
281     return false;
282   }
283 
284   if (!reg4.is_valid()) {
285     return true;
286   } else if (reg4.code() != ((reg3.code() + 1) % kNumberOfVRegisters)) {
287     return false;
288   }
289 
290   return true;
291 }
292 
NeedsRelocation(const Assembler * assembler) const293 bool Operand::NeedsRelocation(const Assembler* assembler) const {
294   RelocInfo::Mode rmode = immediate_.rmode();
295 
296   if (RelocInfo::IsOnlyForSerializer(rmode)) {
297     return assembler->options().record_reloc_info_for_serialization;
298   }
299 
300   return !RelocInfo::IsNone(rmode);
301 }
302 
303 // Assembler
Assembler(const AssemblerOptions & options,std::unique_ptr<AssemblerBuffer> buffer)304 Assembler::Assembler(const AssemblerOptions& options,
305                      std::unique_ptr<AssemblerBuffer> buffer)
306     : AssemblerBase(options, std::move(buffer)),
307       unresolved_branches_(),
308       constpool_(this) {
309   veneer_pool_blocked_nesting_ = 0;
310   Reset();
311 
312 #if defined(V8_OS_WIN)
313   if (options.collect_win64_unwind_info) {
314     xdata_encoder_ = std::make_unique<win64_unwindinfo::XdataEncoder>(*this);
315   }
316 #endif
317 }
318 
~Assembler()319 Assembler::~Assembler() {
320   DCHECK(constpool_.IsEmpty());
321   DCHECK_EQ(veneer_pool_blocked_nesting_, 0);
322 }
323 
AbortedCodeGeneration()324 void Assembler::AbortedCodeGeneration() { constpool_.Clear(); }
325 
Reset()326 void Assembler::Reset() {
327 #ifdef DEBUG
328   DCHECK((pc_ >= buffer_start_) && (pc_ < buffer_start_ + buffer_->size()));
329   DCHECK_EQ(veneer_pool_blocked_nesting_, 0);
330   DCHECK(unresolved_branches_.empty());
331   memset(buffer_start_, 0, pc_ - buffer_start_);
332 #endif
333   pc_ = buffer_start_;
334   reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
335   constpool_.Clear();
336   next_veneer_pool_check_ = kMaxInt;
337 }
338 
339 #if defined(V8_OS_WIN)
GetUnwindInfo() const340 win64_unwindinfo::BuiltinUnwindInfo Assembler::GetUnwindInfo() const {
341   DCHECK(options().collect_win64_unwind_info);
342   DCHECK_NOT_NULL(xdata_encoder_);
343   return xdata_encoder_->unwinding_info();
344 }
345 #endif
346 
AllocateAndInstallRequestedHeapObjects(Isolate * isolate)347 void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
348   DCHECK_IMPLIES(isolate == nullptr, heap_object_requests_.empty());
349   for (auto& request : heap_object_requests_) {
350     Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
351     switch (request.kind()) {
352       case HeapObjectRequest::kHeapNumber: {
353         Handle<HeapObject> object =
354             isolate->factory()->NewHeapNumber<AllocationType::kOld>(
355                 request.heap_number());
356         EmbeddedObjectIndex index = AddEmbeddedObject(object);
357         set_embedded_object_index_referenced_from(pc, index);
358         break;
359       }
360       case HeapObjectRequest::kStringConstant: {
361         const StringConstantBase* str = request.string();
362         CHECK_NOT_NULL(str);
363         EmbeddedObjectIndex index =
364             AddEmbeddedObject(str->AllocateStringConstant(isolate));
365         set_embedded_object_index_referenced_from(pc, index);
366         break;
367       }
368     }
369   }
370 }
371 
GetCode(Isolate * isolate,CodeDesc * desc,SafepointTableBuilder * safepoint_table_builder,int handler_table_offset)372 void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
373                         SafepointTableBuilder* safepoint_table_builder,
374                         int handler_table_offset) {
375   // As a crutch to avoid having to add manual Align calls wherever we use a
376   // raw workflow to create Code objects (mostly in tests), add another Align
377   // call here. It does no harm - the end of the Code object is aligned to the
378   // (larger) kCodeAlignment anyways.
379   // TODO(jgruber): Consider moving responsibility for proper alignment to
380   // metadata table builders (safepoint, handler, constant pool, code
381   // comments).
382   DataAlign(Code::kMetadataAlignment);
383 
384   // Emit constant pool if necessary.
385   ForceConstantPoolEmissionWithoutJump();
386   DCHECK(constpool_.IsEmpty());
387 
388   int code_comments_size = WriteCodeComments();
389 
390   AllocateAndInstallRequestedHeapObjects(isolate);
391 
392   // Set up code descriptor.
393   // TODO(jgruber): Reconsider how these offsets and sizes are maintained up to
394   // this point to make CodeDesc initialization less fiddly.
395 
396   static constexpr int kConstantPoolSize = 0;
397   const int instruction_size = pc_offset();
398   const int code_comments_offset = instruction_size - code_comments_size;
399   const int constant_pool_offset = code_comments_offset - kConstantPoolSize;
400   const int handler_table_offset2 = (handler_table_offset == kNoHandlerTable)
401                                         ? constant_pool_offset
402                                         : handler_table_offset;
403   const int safepoint_table_offset =
404       (safepoint_table_builder == kNoSafepointTable)
405           ? handler_table_offset2
406           : safepoint_table_builder->GetCodeOffset();
407   const int reloc_info_offset =
408       static_cast<int>(reloc_info_writer.pos() - buffer_->start());
409   CodeDesc::Initialize(desc, this, safepoint_table_offset,
410                        handler_table_offset2, constant_pool_offset,
411                        code_comments_offset, reloc_info_offset);
412 }
413 
Align(int m)414 void Assembler::Align(int m) {
415   // If not, the loop below won't terminate.
416   DCHECK(IsAligned(pc_offset(), kInstrSize));
417   DCHECK(m >= kInstrSize && base::bits::IsPowerOfTwo(m));
418   while ((pc_offset() & (m - 1)) != 0) {
419     nop();
420   }
421 }
422 
CodeTargetAlign()423 void Assembler::CodeTargetAlign() {
424   // Preferred alignment of jump targets on some ARM chips.
425   Align(8);
426 }
427 
CheckLabelLinkChain(Label const * label)428 void Assembler::CheckLabelLinkChain(Label const* label) {
429 #ifdef DEBUG
430   if (label->is_linked()) {
431     static const int kMaxLinksToCheck = 64;  // Avoid O(n2) behaviour.
432     int links_checked = 0;
433     int64_t linkoffset = label->pos();
434     bool end_of_chain = false;
435     while (!end_of_chain) {
436       if (++links_checked > kMaxLinksToCheck) break;
437       Instruction* link = InstructionAt(linkoffset);
438       int64_t linkpcoffset = link->ImmPCOffset();
439       int64_t prevlinkoffset = linkoffset + linkpcoffset;
440 
441       end_of_chain = (linkoffset == prevlinkoffset);
442       linkoffset = linkoffset + linkpcoffset;
443     }
444   }
445 #endif
446 }
447 
RemoveBranchFromLabelLinkChain(Instruction * branch,Label * label,Instruction * label_veneer)448 void Assembler::RemoveBranchFromLabelLinkChain(Instruction* branch,
449                                                Label* label,
450                                                Instruction* label_veneer) {
451   DCHECK(label->is_linked());
452 
453   CheckLabelLinkChain(label);
454 
455   Instruction* link = InstructionAt(label->pos());
456   Instruction* prev_link = link;
457   Instruction* next_link;
458   bool end_of_chain = false;
459 
460   while (link != branch && !end_of_chain) {
461     next_link = link->ImmPCOffsetTarget();
462     end_of_chain = (link == next_link);
463     prev_link = link;
464     link = next_link;
465   }
466 
467   DCHECK(branch == link);
468   next_link = branch->ImmPCOffsetTarget();
469 
470   if (branch == prev_link) {
471     // The branch is the first instruction in the chain.
472     if (branch == next_link) {
473       // It is also the last instruction in the chain, so it is the only branch
474       // currently referring to this label.
475       label->Unuse();
476     } else {
477       label->link_to(
478           static_cast<int>(reinterpret_cast<byte*>(next_link) - buffer_start_));
479     }
480 
481   } else if (branch == next_link) {
482     // The branch is the last (but not also the first) instruction in the chain.
483     prev_link->SetImmPCOffsetTarget(options(), prev_link);
484 
485   } else {
486     // The branch is in the middle of the chain.
487     if (prev_link->IsTargetInImmPCOffsetRange(next_link)) {
488       prev_link->SetImmPCOffsetTarget(options(), next_link);
489     } else if (label_veneer != nullptr) {
490       // Use the veneer for all previous links in the chain.
491       prev_link->SetImmPCOffsetTarget(options(), prev_link);
492 
493       end_of_chain = false;
494       link = next_link;
495       while (!end_of_chain) {
496         next_link = link->ImmPCOffsetTarget();
497         end_of_chain = (link == next_link);
498         link->SetImmPCOffsetTarget(options(), label_veneer);
499         link = next_link;
500       }
501     } else {
502       // The assert below will fire.
503       // Some other work could be attempted to fix up the chain, but it would be
504       // rather complicated. If we crash here, we may want to consider using an
505       // other mechanism than a chain of branches.
506       //
507       // Note that this situation currently should not happen, as we always call
508       // this function with a veneer to the target label.
509       // However this could happen with a MacroAssembler in the following state:
510       //    [previous code]
511       //    B(label);
512       //    [20KB code]
513       //    Tbz(label);   // First tbz. Pointing to unconditional branch.
514       //    [20KB code]
515       //    Tbz(label);   // Second tbz. Pointing to the first tbz.
516       //    [more code]
517       // and this function is called to remove the first tbz from the label link
518       // chain. Since tbz has a range of +-32KB, the second tbz cannot point to
519       // the unconditional branch.
520       CHECK(prev_link->IsTargetInImmPCOffsetRange(next_link));
521       UNREACHABLE();
522     }
523   }
524 
525   CheckLabelLinkChain(label);
526 }
527 
bind(Label * label)528 void Assembler::bind(Label* label) {
529   // Bind label to the address at pc_. All instructions (most likely branches)
530   // that are linked to this label will be updated to point to the newly-bound
531   // label.
532 
533   DCHECK(!label->is_near_linked());
534   DCHECK(!label->is_bound());
535 
536   DeleteUnresolvedBranchInfoForLabel(label);
537 
538   // If the label is linked, the link chain looks something like this:
539   //
540   // |--I----I-------I-------L
541   // |---------------------->| pc_offset
542   // |-------------->|         linkoffset = label->pos()
543   //         |<------|         link->ImmPCOffset()
544   // |------>|                 prevlinkoffset = linkoffset + link->ImmPCOffset()
545   //
546   // On each iteration, the last link is updated and then removed from the
547   // chain until only one remains. At that point, the label is bound.
548   //
549   // If the label is not linked, no preparation is required before binding.
550   while (label->is_linked()) {
551     int linkoffset = label->pos();
552     Instruction* link = InstructionAt(linkoffset);
553     int prevlinkoffset = linkoffset + static_cast<int>(link->ImmPCOffset());
554 
555     CheckLabelLinkChain(label);
556 
557     DCHECK_GE(linkoffset, 0);
558     DCHECK(linkoffset < pc_offset());
559     DCHECK((linkoffset > prevlinkoffset) ||
560            (linkoffset - prevlinkoffset == kStartOfLabelLinkChain));
561     DCHECK_GE(prevlinkoffset, 0);
562 
563     // Update the link to point to the label.
564     if (link->IsUnresolvedInternalReference()) {
565       // Internal references do not get patched to an instruction but directly
566       // to an address.
567       internal_reference_positions_.push_back(linkoffset);
568       PatchingAssembler patcher(options(), reinterpret_cast<byte*>(link), 2);
569       patcher.dc64(reinterpret_cast<uintptr_t>(pc_));
570     } else {
571       link->SetImmPCOffsetTarget(options(),
572                                  reinterpret_cast<Instruction*>(pc_));
573     }
574 
575     // Link the label to the previous link in the chain.
576     if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) {
577       // We hit kStartOfLabelLinkChain, so the chain is fully processed.
578       label->Unuse();
579     } else {
580       // Update the label for the next iteration.
581       label->link_to(prevlinkoffset);
582     }
583   }
584   label->bind_to(pc_offset());
585 
586   DCHECK(label->is_bound());
587   DCHECK(!label->is_linked());
588 }
589 
LinkAndGetByteOffsetTo(Label * label)590 int Assembler::LinkAndGetByteOffsetTo(Label* label) {
591   DCHECK_EQ(sizeof(*pc_), 1);
592   CheckLabelLinkChain(label);
593 
594   int offset;
595   if (label->is_bound()) {
596     // The label is bound, so it does not need to be updated. Referring
597     // instructions must link directly to the label as they will not be
598     // updated.
599     //
600     // In this case, label->pos() returns the offset of the label from the
601     // start of the buffer.
602     //
603     // Note that offset can be zero for self-referential instructions. (This
604     // could be useful for ADR, for example.)
605     offset = label->pos() - pc_offset();
606     DCHECK_LE(offset, 0);
607   } else {
608     if (label->is_linked()) {
609       // The label is linked, so the referring instruction should be added onto
610       // the end of the label's link chain.
611       //
612       // In this case, label->pos() returns the offset of the last linked
613       // instruction from the start of the buffer.
614       offset = label->pos() - pc_offset();
615       DCHECK_NE(offset, kStartOfLabelLinkChain);
616       // Note that the offset here needs to be PC-relative only so that the
617       // first instruction in a buffer can link to an unbound label. Otherwise,
618       // the offset would be 0 for this case, and 0 is reserved for
619       // kStartOfLabelLinkChain.
620     } else {
621       // The label is unused, so it now becomes linked and the referring
622       // instruction is at the start of the new link chain.
623       offset = kStartOfLabelLinkChain;
624     }
625     // The instruction at pc is now the last link in the label's chain.
626     label->link_to(pc_offset());
627   }
628 
629   return offset;
630 }
631 
DeleteUnresolvedBranchInfoForLabelTraverse(Label * label)632 void Assembler::DeleteUnresolvedBranchInfoForLabelTraverse(Label* label) {
633   DCHECK(label->is_linked());
634   CheckLabelLinkChain(label);
635 
636   int link_offset = label->pos();
637   int link_pcoffset;
638   bool end_of_chain = false;
639 
640   while (!end_of_chain) {
641     Instruction* link = InstructionAt(link_offset);
642     link_pcoffset = static_cast<int>(link->ImmPCOffset());
643 
644     // ADR instructions are not handled by veneers.
645     if (link->IsImmBranch()) {
646       int max_reachable_pc =
647           static_cast<int>(InstructionOffset(link) +
648                            Instruction::ImmBranchRange(link->BranchType()));
649       using unresolved_info_it = std::multimap<int, FarBranchInfo>::iterator;
650       std::pair<unresolved_info_it, unresolved_info_it> range;
651       range = unresolved_branches_.equal_range(max_reachable_pc);
652       unresolved_info_it it;
653       for (it = range.first; it != range.second; ++it) {
654         if (it->second.pc_offset_ == link_offset) {
655           unresolved_branches_.erase(it);
656           break;
657         }
658       }
659     }
660 
661     end_of_chain = (link_pcoffset == 0);
662     link_offset = link_offset + link_pcoffset;
663   }
664 }
665 
DeleteUnresolvedBranchInfoForLabel(Label * label)666 void Assembler::DeleteUnresolvedBranchInfoForLabel(Label* label) {
667   if (unresolved_branches_.empty()) {
668     DCHECK_EQ(next_veneer_pool_check_, kMaxInt);
669     return;
670   }
671 
672   if (label->is_linked()) {
673     // Branches to this label will be resolved when the label is bound, normally
674     // just after all the associated info has been deleted.
675     DeleteUnresolvedBranchInfoForLabelTraverse(label);
676   }
677   if (unresolved_branches_.empty()) {
678     next_veneer_pool_check_ = kMaxInt;
679   } else {
680     next_veneer_pool_check_ =
681         unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
682   }
683 }
684 
IsConstantPoolAt(Instruction * instr)685 bool Assembler::IsConstantPoolAt(Instruction* instr) {
686   // The constant pool marker is made of two instructions. These instructions
687   // will never be emitted by the JIT, so checking for the first one is enough:
688   // 0: ldr xzr, #<size of pool>
689   bool result = instr->IsLdrLiteralX() && (instr->Rt() == kZeroRegCode);
690 
691   // It is still worth asserting the marker is complete.
692   // 4: blr xzr
693   DCHECK(!result || (instr->following()->IsBranchAndLinkToRegister() &&
694                      instr->following()->Rn() == kZeroRegCode));
695 
696   return result;
697 }
698 
ConstantPoolSizeAt(Instruction * instr)699 int Assembler::ConstantPoolSizeAt(Instruction* instr) {
700 #ifdef USE_SIMULATOR
701   // Assembler::debug() embeds constants directly into the instruction stream.
702   // Although this is not a genuine constant pool, treat it like one to avoid
703   // disassembling the constants.
704   if ((instr->Mask(ExceptionMask) == HLT) &&
705       (instr->ImmException() == kImmExceptionIsDebug)) {
706     const char* message = reinterpret_cast<const char*>(
707         instr->InstructionAtOffset(kDebugMessageOffset));
708     int size = static_cast<int>(kDebugMessageOffset + strlen(message) + 1);
709     return RoundUp(size, kInstrSize) / kInstrSize;
710   }
711   // Same for printf support, see MacroAssembler::CallPrintf().
712   if ((instr->Mask(ExceptionMask) == HLT) &&
713       (instr->ImmException() == kImmExceptionIsPrintf)) {
714     return kPrintfLength / kInstrSize;
715   }
716 #endif
717   if (IsConstantPoolAt(instr)) {
718     return instr->ImmLLiteral();
719   } else {
720     return -1;
721   }
722 }
723 
EmitPoolGuard()724 void Assembler::EmitPoolGuard() {
725   // We must generate only one instruction as this is used in scopes that
726   // control the size of the code generated.
727   Emit(BLR | Rn(xzr));
728 }
729 
StartBlockVeneerPool()730 void Assembler::StartBlockVeneerPool() { ++veneer_pool_blocked_nesting_; }
731 
EndBlockVeneerPool()732 void Assembler::EndBlockVeneerPool() {
733   if (--veneer_pool_blocked_nesting_ == 0) {
734     // Check the veneer pool hasn't been blocked for too long.
735     DCHECK(unresolved_branches_.empty() ||
736            (pc_offset() < unresolved_branches_first_limit()));
737   }
738 }
739 
br(const Register & xn)740 void Assembler::br(const Register& xn) {
741   DCHECK(xn.Is64Bits());
742   Emit(BR | Rn(xn));
743 }
744 
blr(const Register & xn)745 void Assembler::blr(const Register& xn) {
746   DCHECK(xn.Is64Bits());
747   // The pattern 'blr xzr' is used as a guard to detect when execution falls
748   // through the constant pool. It should not be emitted.
749   DCHECK_NE(xn, xzr);
750   Emit(BLR | Rn(xn));
751 }
752 
ret(const Register & xn)753 void Assembler::ret(const Register& xn) {
754   DCHECK(xn.Is64Bits());
755   Emit(RET | Rn(xn));
756 }
757 
b(int imm26)758 void Assembler::b(int imm26) { Emit(B | ImmUncondBranch(imm26)); }
759 
b(Label * label)760 void Assembler::b(Label* label) { b(LinkAndGetInstructionOffsetTo(label)); }
761 
b(int imm19,Condition cond)762 void Assembler::b(int imm19, Condition cond) {
763   Emit(B_cond | ImmCondBranch(imm19) | cond);
764 }
765 
b(Label * label,Condition cond)766 void Assembler::b(Label* label, Condition cond) {
767   b(LinkAndGetInstructionOffsetTo(label), cond);
768 }
769 
bl(int imm26)770 void Assembler::bl(int imm26) { Emit(BL | ImmUncondBranch(imm26)); }
771 
bl(Label * label)772 void Assembler::bl(Label* label) { bl(LinkAndGetInstructionOffsetTo(label)); }
773 
cbz(const Register & rt,int imm19)774 void Assembler::cbz(const Register& rt, int imm19) {
775   Emit(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt));
776 }
777 
cbz(const Register & rt,Label * label)778 void Assembler::cbz(const Register& rt, Label* label) {
779   cbz(rt, LinkAndGetInstructionOffsetTo(label));
780 }
781 
cbnz(const Register & rt,int imm19)782 void Assembler::cbnz(const Register& rt, int imm19) {
783   Emit(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt));
784 }
785 
cbnz(const Register & rt,Label * label)786 void Assembler::cbnz(const Register& rt, Label* label) {
787   cbnz(rt, LinkAndGetInstructionOffsetTo(label));
788 }
789 
tbz(const Register & rt,unsigned bit_pos,int imm14)790 void Assembler::tbz(const Register& rt, unsigned bit_pos, int imm14) {
791   DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
792   Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
793 }
794 
tbz(const Register & rt,unsigned bit_pos,Label * label)795 void Assembler::tbz(const Register& rt, unsigned bit_pos, Label* label) {
796   tbz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
797 }
798 
tbnz(const Register & rt,unsigned bit_pos,int imm14)799 void Assembler::tbnz(const Register& rt, unsigned bit_pos, int imm14) {
800   DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
801   Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
802 }
803 
tbnz(const Register & rt,unsigned bit_pos,Label * label)804 void Assembler::tbnz(const Register& rt, unsigned bit_pos, Label* label) {
805   tbnz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
806 }
807 
adr(const Register & rd,int imm21)808 void Assembler::adr(const Register& rd, int imm21) {
809   DCHECK(rd.Is64Bits());
810   Emit(ADR | ImmPCRelAddress(imm21) | Rd(rd));
811 }
812 
adr(const Register & rd,Label * label)813 void Assembler::adr(const Register& rd, Label* label) {
814   adr(rd, LinkAndGetByteOffsetTo(label));
815 }
816 
nop(NopMarkerTypes n)817 void Assembler::nop(NopMarkerTypes n) {
818   DCHECK((FIRST_NOP_MARKER <= n) && (n <= LAST_NOP_MARKER));
819   mov(Register::XRegFromCode(n), Register::XRegFromCode(n));
820 }
821 
add(const Register & rd,const Register & rn,const Operand & operand)822 void Assembler::add(const Register& rd, const Register& rn,
823                     const Operand& operand) {
824   AddSub(rd, rn, operand, LeaveFlags, ADD);
825 }
826 
adds(const Register & rd,const Register & rn,const Operand & operand)827 void Assembler::adds(const Register& rd, const Register& rn,
828                      const Operand& operand) {
829   AddSub(rd, rn, operand, SetFlags, ADD);
830 }
831 
cmn(const Register & rn,const Operand & operand)832 void Assembler::cmn(const Register& rn, const Operand& operand) {
833   Register zr = AppropriateZeroRegFor(rn);
834   adds(zr, rn, operand);
835 }
836 
sub(const Register & rd,const Register & rn,const Operand & operand)837 void Assembler::sub(const Register& rd, const Register& rn,
838                     const Operand& operand) {
839   AddSub(rd, rn, operand, LeaveFlags, SUB);
840 }
841 
subs(const Register & rd,const Register & rn,const Operand & operand)842 void Assembler::subs(const Register& rd, const Register& rn,
843                      const Operand& operand) {
844   AddSub(rd, rn, operand, SetFlags, SUB);
845 }
846 
cmp(const Register & rn,const Operand & operand)847 void Assembler::cmp(const Register& rn, const Operand& operand) {
848   Register zr = AppropriateZeroRegFor(rn);
849   subs(zr, rn, operand);
850 }
851 
neg(const Register & rd,const Operand & operand)852 void Assembler::neg(const Register& rd, const Operand& operand) {
853   Register zr = AppropriateZeroRegFor(rd);
854   sub(rd, zr, operand);
855 }
856 
negs(const Register & rd,const Operand & operand)857 void Assembler::negs(const Register& rd, const Operand& operand) {
858   Register zr = AppropriateZeroRegFor(rd);
859   subs(rd, zr, operand);
860 }
861 
adc(const Register & rd,const Register & rn,const Operand & operand)862 void Assembler::adc(const Register& rd, const Register& rn,
863                     const Operand& operand) {
864   AddSubWithCarry(rd, rn, operand, LeaveFlags, ADC);
865 }
866 
adcs(const Register & rd,const Register & rn,const Operand & operand)867 void Assembler::adcs(const Register& rd, const Register& rn,
868                      const Operand& operand) {
869   AddSubWithCarry(rd, rn, operand, SetFlags, ADC);
870 }
871 
sbc(const Register & rd,const Register & rn,const Operand & operand)872 void Assembler::sbc(const Register& rd, const Register& rn,
873                     const Operand& operand) {
874   AddSubWithCarry(rd, rn, operand, LeaveFlags, SBC);
875 }
876 
sbcs(const Register & rd,const Register & rn,const Operand & operand)877 void Assembler::sbcs(const Register& rd, const Register& rn,
878                      const Operand& operand) {
879   AddSubWithCarry(rd, rn, operand, SetFlags, SBC);
880 }
881 
ngc(const Register & rd,const Operand & operand)882 void Assembler::ngc(const Register& rd, const Operand& operand) {
883   Register zr = AppropriateZeroRegFor(rd);
884   sbc(rd, zr, operand);
885 }
886 
ngcs(const Register & rd,const Operand & operand)887 void Assembler::ngcs(const Register& rd, const Operand& operand) {
888   Register zr = AppropriateZeroRegFor(rd);
889   sbcs(rd, zr, operand);
890 }
891 
892 // Logical instructions.
and_(const Register & rd,const Register & rn,const Operand & operand)893 void Assembler::and_(const Register& rd, const Register& rn,
894                      const Operand& operand) {
895   Logical(rd, rn, operand, AND);
896 }
897 
ands(const Register & rd,const Register & rn,const Operand & operand)898 void Assembler::ands(const Register& rd, const Register& rn,
899                      const Operand& operand) {
900   Logical(rd, rn, operand, ANDS);
901 }
902 
tst(const Register & rn,const Operand & operand)903 void Assembler::tst(const Register& rn, const Operand& operand) {
904   ands(AppropriateZeroRegFor(rn), rn, operand);
905 }
906 
bic(const Register & rd,const Register & rn,const Operand & operand)907 void Assembler::bic(const Register& rd, const Register& rn,
908                     const Operand& operand) {
909   Logical(rd, rn, operand, BIC);
910 }
911 
bics(const Register & rd,const Register & rn,const Operand & operand)912 void Assembler::bics(const Register& rd, const Register& rn,
913                      const Operand& operand) {
914   Logical(rd, rn, operand, BICS);
915 }
916 
orr(const Register & rd,const Register & rn,const Operand & operand)917 void Assembler::orr(const Register& rd, const Register& rn,
918                     const Operand& operand) {
919   Logical(rd, rn, operand, ORR);
920 }
921 
orn(const Register & rd,const Register & rn,const Operand & operand)922 void Assembler::orn(const Register& rd, const Register& rn,
923                     const Operand& operand) {
924   Logical(rd, rn, operand, ORN);
925 }
926 
eor(const Register & rd,const Register & rn,const Operand & operand)927 void Assembler::eor(const Register& rd, const Register& rn,
928                     const Operand& operand) {
929   Logical(rd, rn, operand, EOR);
930 }
931 
eon(const Register & rd,const Register & rn,const Operand & operand)932 void Assembler::eon(const Register& rd, const Register& rn,
933                     const Operand& operand) {
934   Logical(rd, rn, operand, EON);
935 }
936 
lslv(const Register & rd,const Register & rn,const Register & rm)937 void Assembler::lslv(const Register& rd, const Register& rn,
938                      const Register& rm) {
939   DCHECK(rd.SizeInBits() == rn.SizeInBits());
940   DCHECK(rd.SizeInBits() == rm.SizeInBits());
941   Emit(SF(rd) | LSLV | Rm(rm) | Rn(rn) | Rd(rd));
942 }
943 
lsrv(const Register & rd,const Register & rn,const Register & rm)944 void Assembler::lsrv(const Register& rd, const Register& rn,
945                      const Register& rm) {
946   DCHECK(rd.SizeInBits() == rn.SizeInBits());
947   DCHECK(rd.SizeInBits() == rm.SizeInBits());
948   Emit(SF(rd) | LSRV | Rm(rm) | Rn(rn) | Rd(rd));
949 }
950 
asrv(const Register & rd,const Register & rn,const Register & rm)951 void Assembler::asrv(const Register& rd, const Register& rn,
952                      const Register& rm) {
953   DCHECK(rd.SizeInBits() == rn.SizeInBits());
954   DCHECK(rd.SizeInBits() == rm.SizeInBits());
955   Emit(SF(rd) | ASRV | Rm(rm) | Rn(rn) | Rd(rd));
956 }
957 
rorv(const Register & rd,const Register & rn,const Register & rm)958 void Assembler::rorv(const Register& rd, const Register& rn,
959                      const Register& rm) {
960   DCHECK(rd.SizeInBits() == rn.SizeInBits());
961   DCHECK(rd.SizeInBits() == rm.SizeInBits());
962   Emit(SF(rd) | RORV | Rm(rm) | Rn(rn) | Rd(rd));
963 }
964 
965 // Bitfield operations.
bfm(const Register & rd,const Register & rn,int immr,int imms)966 void Assembler::bfm(const Register& rd, const Register& rn, int immr,
967                     int imms) {
968   DCHECK(rd.SizeInBits() == rn.SizeInBits());
969   Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
970   Emit(SF(rd) | BFM | N | ImmR(immr, rd.SizeInBits()) |
971        ImmS(imms, rn.SizeInBits()) | Rn(rn) | Rd(rd));
972 }
973 
sbfm(const Register & rd,const Register & rn,int immr,int imms)974 void Assembler::sbfm(const Register& rd, const Register& rn, int immr,
975                      int imms) {
976   DCHECK(rd.Is64Bits() || rn.Is32Bits());
977   Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
978   Emit(SF(rd) | SBFM | N | ImmR(immr, rd.SizeInBits()) |
979        ImmS(imms, rn.SizeInBits()) | Rn(rn) | Rd(rd));
980 }
981 
ubfm(const Register & rd,const Register & rn,int immr,int imms)982 void Assembler::ubfm(const Register& rd, const Register& rn, int immr,
983                      int imms) {
984   DCHECK(rd.SizeInBits() == rn.SizeInBits());
985   Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
986   Emit(SF(rd) | UBFM | N | ImmR(immr, rd.SizeInBits()) |
987        ImmS(imms, rn.SizeInBits()) | Rn(rn) | Rd(rd));
988 }
989 
extr(const Register & rd,const Register & rn,const Register & rm,int lsb)990 void Assembler::extr(const Register& rd, const Register& rn, const Register& rm,
991                      int lsb) {
992   DCHECK(rd.SizeInBits() == rn.SizeInBits());
993   DCHECK(rd.SizeInBits() == rm.SizeInBits());
994   Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
995   Emit(SF(rd) | EXTR | N | Rm(rm) | ImmS(lsb, rn.SizeInBits()) | Rn(rn) |
996        Rd(rd));
997 }
998 
csel(const Register & rd,const Register & rn,const Register & rm,Condition cond)999 void Assembler::csel(const Register& rd, const Register& rn, const Register& rm,
1000                      Condition cond) {
1001   ConditionalSelect(rd, rn, rm, cond, CSEL);
1002 }
1003 
csinc(const Register & rd,const Register & rn,const Register & rm,Condition cond)1004 void Assembler::csinc(const Register& rd, const Register& rn,
1005                       const Register& rm, Condition cond) {
1006   ConditionalSelect(rd, rn, rm, cond, CSINC);
1007 }
1008 
csinv(const Register & rd,const Register & rn,const Register & rm,Condition cond)1009 void Assembler::csinv(const Register& rd, const Register& rn,
1010                       const Register& rm, Condition cond) {
1011   ConditionalSelect(rd, rn, rm, cond, CSINV);
1012 }
1013 
csneg(const Register & rd,const Register & rn,const Register & rm,Condition cond)1014 void Assembler::csneg(const Register& rd, const Register& rn,
1015                       const Register& rm, Condition cond) {
1016   ConditionalSelect(rd, rn, rm, cond, CSNEG);
1017 }
1018 
cset(const Register & rd,Condition cond)1019 void Assembler::cset(const Register& rd, Condition cond) {
1020   DCHECK((cond != al) && (cond != nv));
1021   Register zr = AppropriateZeroRegFor(rd);
1022   csinc(rd, zr, zr, NegateCondition(cond));
1023 }
1024 
csetm(const Register & rd,Condition cond)1025 void Assembler::csetm(const Register& rd, Condition cond) {
1026   DCHECK((cond != al) && (cond != nv));
1027   Register zr = AppropriateZeroRegFor(rd);
1028   csinv(rd, zr, zr, NegateCondition(cond));
1029 }
1030 
cinc(const Register & rd,const Register & rn,Condition cond)1031 void Assembler::cinc(const Register& rd, const Register& rn, Condition cond) {
1032   DCHECK((cond != al) && (cond != nv));
1033   csinc(rd, rn, rn, NegateCondition(cond));
1034 }
1035 
cinv(const Register & rd,const Register & rn,Condition cond)1036 void Assembler::cinv(const Register& rd, const Register& rn, Condition cond) {
1037   DCHECK((cond != al) && (cond != nv));
1038   csinv(rd, rn, rn, NegateCondition(cond));
1039 }
1040 
cneg(const Register & rd,const Register & rn,Condition cond)1041 void Assembler::cneg(const Register& rd, const Register& rn, Condition cond) {
1042   DCHECK((cond != al) && (cond != nv));
1043   csneg(rd, rn, rn, NegateCondition(cond));
1044 }
1045 
ConditionalSelect(const Register & rd,const Register & rn,const Register & rm,Condition cond,ConditionalSelectOp op)1046 void Assembler::ConditionalSelect(const Register& rd, const Register& rn,
1047                                   const Register& rm, Condition cond,
1048                                   ConditionalSelectOp op) {
1049   DCHECK(rd.SizeInBits() == rn.SizeInBits());
1050   DCHECK(rd.SizeInBits() == rm.SizeInBits());
1051   Emit(SF(rd) | op | Rm(rm) | Cond(cond) | Rn(rn) | Rd(rd));
1052 }
1053 
ccmn(const Register & rn,const Operand & operand,StatusFlags nzcv,Condition cond)1054 void Assembler::ccmn(const Register& rn, const Operand& operand,
1055                      StatusFlags nzcv, Condition cond) {
1056   ConditionalCompare(rn, operand, nzcv, cond, CCMN);
1057 }
1058 
ccmp(const Register & rn,const Operand & operand,StatusFlags nzcv,Condition cond)1059 void Assembler::ccmp(const Register& rn, const Operand& operand,
1060                      StatusFlags nzcv, Condition cond) {
1061   ConditionalCompare(rn, operand, nzcv, cond, CCMP);
1062 }
1063 
DataProcessing3Source(const Register & rd,const Register & rn,const Register & rm,const Register & ra,DataProcessing3SourceOp op)1064 void Assembler::DataProcessing3Source(const Register& rd, const Register& rn,
1065                                       const Register& rm, const Register& ra,
1066                                       DataProcessing3SourceOp op) {
1067   Emit(SF(rd) | op | Rm(rm) | Ra(ra) | Rn(rn) | Rd(rd));
1068 }
1069 
mul(const Register & rd,const Register & rn,const Register & rm)1070 void Assembler::mul(const Register& rd, const Register& rn,
1071                     const Register& rm) {
1072   DCHECK(AreSameSizeAndType(rd, rn, rm));
1073   Register zr = AppropriateZeroRegFor(rn);
1074   DataProcessing3Source(rd, rn, rm, zr, MADD);
1075 }
1076 
madd(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1077 void Assembler::madd(const Register& rd, const Register& rn, const Register& rm,
1078                      const Register& ra) {
1079   DCHECK(AreSameSizeAndType(rd, rn, rm, ra));
1080   DataProcessing3Source(rd, rn, rm, ra, MADD);
1081 }
1082 
mneg(const Register & rd,const Register & rn,const Register & rm)1083 void Assembler::mneg(const Register& rd, const Register& rn,
1084                      const Register& rm) {
1085   DCHECK(AreSameSizeAndType(rd, rn, rm));
1086   Register zr = AppropriateZeroRegFor(rn);
1087   DataProcessing3Source(rd, rn, rm, zr, MSUB);
1088 }
1089 
msub(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1090 void Assembler::msub(const Register& rd, const Register& rn, const Register& rm,
1091                      const Register& ra) {
1092   DCHECK(AreSameSizeAndType(rd, rn, rm, ra));
1093   DataProcessing3Source(rd, rn, rm, ra, MSUB);
1094 }
1095 
smaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1096 void Assembler::smaddl(const Register& rd, const Register& rn,
1097                        const Register& rm, const Register& ra) {
1098   DCHECK(rd.Is64Bits() && ra.Is64Bits());
1099   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1100   DataProcessing3Source(rd, rn, rm, ra, SMADDL_x);
1101 }
1102 
smsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1103 void Assembler::smsubl(const Register& rd, const Register& rn,
1104                        const Register& rm, const Register& ra) {
1105   DCHECK(rd.Is64Bits() && ra.Is64Bits());
1106   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1107   DataProcessing3Source(rd, rn, rm, ra, SMSUBL_x);
1108 }
1109 
umaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1110 void Assembler::umaddl(const Register& rd, const Register& rn,
1111                        const Register& rm, const Register& ra) {
1112   DCHECK(rd.Is64Bits() && ra.Is64Bits());
1113   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1114   DataProcessing3Source(rd, rn, rm, ra, UMADDL_x);
1115 }
1116 
umsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1117 void Assembler::umsubl(const Register& rd, const Register& rn,
1118                        const Register& rm, const Register& ra) {
1119   DCHECK(rd.Is64Bits() && ra.Is64Bits());
1120   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1121   DataProcessing3Source(rd, rn, rm, ra, UMSUBL_x);
1122 }
1123 
smull(const Register & rd,const Register & rn,const Register & rm)1124 void Assembler::smull(const Register& rd, const Register& rn,
1125                       const Register& rm) {
1126   DCHECK(rd.Is64Bits());
1127   DCHECK(rn.Is32Bits() && rm.Is32Bits());
1128   DataProcessing3Source(rd, rn, rm, xzr, SMADDL_x);
1129 }
1130 
smulh(const Register & rd,const Register & rn,const Register & rm)1131 void Assembler::smulh(const Register& rd, const Register& rn,
1132                       const Register& rm) {
1133   DCHECK(AreSameSizeAndType(rd, rn, rm));
1134   DataProcessing3Source(rd, rn, rm, xzr, SMULH_x);
1135 }
1136 
sdiv(const Register & rd,const Register & rn,const Register & rm)1137 void Assembler::sdiv(const Register& rd, const Register& rn,
1138                      const Register& rm) {
1139   DCHECK(rd.SizeInBits() == rn.SizeInBits());
1140   DCHECK(rd.SizeInBits() == rm.SizeInBits());
1141   Emit(SF(rd) | SDIV | Rm(rm) | Rn(rn) | Rd(rd));
1142 }
1143 
udiv(const Register & rd,const Register & rn,const Register & rm)1144 void Assembler::udiv(const Register& rd, const Register& rn,
1145                      const Register& rm) {
1146   DCHECK(rd.SizeInBits() == rn.SizeInBits());
1147   DCHECK(rd.SizeInBits() == rm.SizeInBits());
1148   Emit(SF(rd) | UDIV | Rm(rm) | Rn(rn) | Rd(rd));
1149 }
1150 
rbit(const Register & rd,const Register & rn)1151 void Assembler::rbit(const Register& rd, const Register& rn) {
1152   DataProcessing1Source(rd, rn, RBIT);
1153 }
1154 
rev16(const Register & rd,const Register & rn)1155 void Assembler::rev16(const Register& rd, const Register& rn) {
1156   DataProcessing1Source(rd, rn, REV16);
1157 }
1158 
rev32(const Register & rd,const Register & rn)1159 void Assembler::rev32(const Register& rd, const Register& rn) {
1160   DCHECK(rd.Is64Bits());
1161   DataProcessing1Source(rd, rn, REV);
1162 }
1163 
rev(const Register & rd,const Register & rn)1164 void Assembler::rev(const Register& rd, const Register& rn) {
1165   DataProcessing1Source(rd, rn, rd.Is64Bits() ? REV_x : REV_w);
1166 }
1167 
clz(const Register & rd,const Register & rn)1168 void Assembler::clz(const Register& rd, const Register& rn) {
1169   DataProcessing1Source(rd, rn, CLZ);
1170 }
1171 
cls(const Register & rd,const Register & rn)1172 void Assembler::cls(const Register& rd, const Register& rn) {
1173   DataProcessing1Source(rd, rn, CLS);
1174 }
1175 
pacib1716()1176 void Assembler::pacib1716() { Emit(PACIB1716); }
autib1716()1177 void Assembler::autib1716() { Emit(AUTIB1716); }
pacibsp()1178 void Assembler::pacibsp() { Emit(PACIBSP); }
autibsp()1179 void Assembler::autibsp() { Emit(AUTIBSP); }
1180 
bti(BranchTargetIdentifier id)1181 void Assembler::bti(BranchTargetIdentifier id) {
1182   SystemHint op;
1183   switch (id) {
1184     case BranchTargetIdentifier::kBti:
1185       op = BTI;
1186       break;
1187     case BranchTargetIdentifier::kBtiCall:
1188       op = BTI_c;
1189       break;
1190     case BranchTargetIdentifier::kBtiJump:
1191       op = BTI_j;
1192       break;
1193     case BranchTargetIdentifier::kBtiJumpCall:
1194       op = BTI_jc;
1195       break;
1196     case BranchTargetIdentifier::kNone:
1197     case BranchTargetIdentifier::kPacibsp:
1198       // We always want to generate a BTI instruction here, so disallow
1199       // skipping its generation or generating a PACIBSP instead.
1200       UNREACHABLE();
1201   }
1202   hint(op);
1203 }
1204 
ldp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & src)1205 void Assembler::ldp(const CPURegister& rt, const CPURegister& rt2,
1206                     const MemOperand& src) {
1207   LoadStorePair(rt, rt2, src, LoadPairOpFor(rt, rt2));
1208 }
1209 
stp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & dst)1210 void Assembler::stp(const CPURegister& rt, const CPURegister& rt2,
1211                     const MemOperand& dst) {
1212   LoadStorePair(rt, rt2, dst, StorePairOpFor(rt, rt2));
1213 
1214 #if defined(V8_OS_WIN)
1215   if (xdata_encoder_ && rt == x29 && rt2 == lr && dst.base().IsSP()) {
1216     xdata_encoder_->onSaveFpLr();
1217   }
1218 #endif
1219 }
1220 
ldpsw(const Register & rt,const Register & rt2,const MemOperand & src)1221 void Assembler::ldpsw(const Register& rt, const Register& rt2,
1222                       const MemOperand& src) {
1223   DCHECK(rt.Is64Bits());
1224   LoadStorePair(rt, rt2, src, LDPSW_x);
1225 }
1226 
LoadStorePair(const CPURegister & rt,const CPURegister & rt2,const MemOperand & addr,LoadStorePairOp op)1227 void Assembler::LoadStorePair(const CPURegister& rt, const CPURegister& rt2,
1228                               const MemOperand& addr, LoadStorePairOp op) {
1229   // 'rt' and 'rt2' can only be aliased for stores.
1230   DCHECK(((op & LoadStorePairLBit) == 0) || rt != rt2);
1231   DCHECK(AreSameSizeAndType(rt, rt2));
1232   DCHECK(IsImmLSPair(addr.offset(), CalcLSPairDataSize(op)));
1233   int offset = static_cast<int>(addr.offset());
1234 
1235   Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
1236                 ImmLSPair(offset, CalcLSPairDataSize(op));
1237 
1238   Instr addrmodeop;
1239   if (addr.IsImmediateOffset()) {
1240     addrmodeop = LoadStorePairOffsetFixed;
1241   } else {
1242     // Pre-index and post-index modes.
1243     DCHECK_NE(rt, addr.base());
1244     DCHECK_NE(rt2, addr.base());
1245     DCHECK_NE(addr.offset(), 0);
1246     if (addr.IsPreIndex()) {
1247       addrmodeop = LoadStorePairPreIndexFixed;
1248     } else {
1249       DCHECK(addr.IsPostIndex());
1250       addrmodeop = LoadStorePairPostIndexFixed;
1251     }
1252   }
1253   Emit(addrmodeop | memop);
1254 }
1255 
1256 // Memory instructions.
ldrb(const Register & rt,const MemOperand & src)1257 void Assembler::ldrb(const Register& rt, const MemOperand& src) {
1258   LoadStore(rt, src, LDRB_w);
1259 }
1260 
strb(const Register & rt,const MemOperand & dst)1261 void Assembler::strb(const Register& rt, const MemOperand& dst) {
1262   LoadStore(rt, dst, STRB_w);
1263 }
1264 
ldrsb(const Register & rt,const MemOperand & src)1265 void Assembler::ldrsb(const Register& rt, const MemOperand& src) {
1266   LoadStore(rt, src, rt.Is64Bits() ? LDRSB_x : LDRSB_w);
1267 }
1268 
ldrh(const Register & rt,const MemOperand & src)1269 void Assembler::ldrh(const Register& rt, const MemOperand& src) {
1270   LoadStore(rt, src, LDRH_w);
1271 }
1272 
strh(const Register & rt,const MemOperand & dst)1273 void Assembler::strh(const Register& rt, const MemOperand& dst) {
1274   LoadStore(rt, dst, STRH_w);
1275 }
1276 
ldrsh(const Register & rt,const MemOperand & src)1277 void Assembler::ldrsh(const Register& rt, const MemOperand& src) {
1278   LoadStore(rt, src, rt.Is64Bits() ? LDRSH_x : LDRSH_w);
1279 }
1280 
ldr(const CPURegister & rt,const MemOperand & src)1281 void Assembler::ldr(const CPURegister& rt, const MemOperand& src) {
1282   LoadStore(rt, src, LoadOpFor(rt));
1283 }
1284 
str(const CPURegister & rt,const MemOperand & src)1285 void Assembler::str(const CPURegister& rt, const MemOperand& src) {
1286   LoadStore(rt, src, StoreOpFor(rt));
1287 }
1288 
ldrsw(const Register & rt,const MemOperand & src)1289 void Assembler::ldrsw(const Register& rt, const MemOperand& src) {
1290   DCHECK(rt.Is64Bits());
1291   LoadStore(rt, src, LDRSW_x);
1292 }
1293 
ldr_pcrel(const CPURegister & rt,int imm19)1294 void Assembler::ldr_pcrel(const CPURegister& rt, int imm19) {
1295   // The pattern 'ldr xzr, #offset' is used to indicate the beginning of a
1296   // constant pool. It should not be emitted.
1297   DCHECK(!rt.IsZero());
1298   Emit(LoadLiteralOpFor(rt) | ImmLLiteral(imm19) | Rt(rt));
1299 }
1300 
EmbeddedNumber(double number)1301 Operand Operand::EmbeddedNumber(double number) {
1302   int32_t smi;
1303   if (DoubleToSmiInteger(number, &smi)) {
1304     return Operand(Immediate(Smi::FromInt(smi)));
1305   }
1306   Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
1307   result.heap_object_request_.emplace(number);
1308   DCHECK(result.IsHeapObjectRequest());
1309   return result;
1310 }
1311 
EmbeddedStringConstant(const StringConstantBase * str)1312 Operand Operand::EmbeddedStringConstant(const StringConstantBase* str) {
1313   Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
1314   result.heap_object_request_.emplace(str);
1315   DCHECK(result.IsHeapObjectRequest());
1316   return result;
1317 }
1318 
ldr(const CPURegister & rt,const Operand & operand)1319 void Assembler::ldr(const CPURegister& rt, const Operand& operand) {
1320   if (operand.IsHeapObjectRequest()) {
1321     BlockPoolsScope no_pool_before_ldr_of_heap_object_request(this);
1322     RequestHeapObject(operand.heap_object_request());
1323     ldr(rt, operand.immediate_for_heap_object_request());
1324   } else {
1325     ldr(rt, operand.immediate());
1326   }
1327 }
1328 
ldr(const CPURegister & rt,const Immediate & imm)1329 void Assembler::ldr(const CPURegister& rt, const Immediate& imm) {
1330   BlockPoolsScope no_pool_before_ldr_pcrel_instr(this);
1331   RecordRelocInfo(imm.rmode(), imm.value());
1332   // The load will be patched when the constpool is emitted, patching code
1333   // expect a load literal with offset 0.
1334   ldr_pcrel(rt, 0);
1335 }
1336 
ldar(const Register & rt,const Register & rn)1337 void Assembler::ldar(const Register& rt, const Register& rn) {
1338   DCHECK(rn.Is64Bits());
1339   LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? LDAR_w : LDAR_x;
1340   Emit(op | Rs(x31) | Rt2(x31) | RnSP(rn) | Rt(rt));
1341 }
1342 
ldaxr(const Register & rt,const Register & rn)1343 void Assembler::ldaxr(const Register& rt, const Register& rn) {
1344   DCHECK(rn.Is64Bits());
1345   LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? LDAXR_w : LDAXR_x;
1346   Emit(op | Rs(x31) | Rt2(x31) | RnSP(rn) | Rt(rt));
1347 }
1348 
stlr(const Register & rt,const Register & rn)1349 void Assembler::stlr(const Register& rt, const Register& rn) {
1350   DCHECK(rn.Is64Bits());
1351   LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? STLR_w : STLR_x;
1352   Emit(op | Rs(x31) | Rt2(x31) | RnSP(rn) | Rt(rt));
1353 }
1354 
stlxr(const Register & rs,const Register & rt,const Register & rn)1355 void Assembler::stlxr(const Register& rs, const Register& rt,
1356                       const Register& rn) {
1357   DCHECK(rn.Is64Bits());
1358   DCHECK(rs != rt && rs != rn);
1359   LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? STLXR_w : STLXR_x;
1360   Emit(op | Rs(rs) | Rt2(x31) | RnSP(rn) | Rt(rt));
1361 }
1362 
ldarb(const Register & rt,const Register & rn)1363 void Assembler::ldarb(const Register& rt, const Register& rn) {
1364   DCHECK(rt.Is32Bits());
1365   DCHECK(rn.Is64Bits());
1366   Emit(LDAR_b | Rs(x31) | Rt2(x31) | RnSP(rn) | Rt(rt));
1367 }
1368 
ldaxrb(const Register & rt,const Register & rn)1369 void Assembler::ldaxrb(const Register& rt, const Register& rn) {
1370   DCHECK(rt.Is32Bits());
1371   DCHECK(rn.Is64Bits());
1372   Emit(LDAXR_b | Rs(x31) | Rt2(x31) | RnSP(rn) | Rt(rt));
1373 }
1374 
stlrb(const Register & rt,const Register & rn)1375 void Assembler::stlrb(const Register& rt, const Register& rn) {
1376   DCHECK(rt.Is32Bits());
1377   DCHECK(rn.Is64Bits());
1378   Emit(STLR_b | Rs(x31) | Rt2(x31) | RnSP(rn) | Rt(rt));
1379 }
1380 
stlxrb(const Register & rs,const Register & rt,const Register & rn)1381 void Assembler::stlxrb(const Register& rs, const Register& rt,
1382                        const Register& rn) {
1383   DCHECK(rs.Is32Bits());
1384   DCHECK(rt.Is32Bits());
1385   DCHECK(rn.Is64Bits());
1386   DCHECK(rs != rt && rs != rn);
1387   Emit(STLXR_b | Rs(rs) | Rt2(x31) | RnSP(rn) | Rt(rt));
1388 }
1389 
ldarh(const Register & rt,const Register & rn)1390 void Assembler::ldarh(const Register& rt, const Register& rn) {
1391   DCHECK(rt.Is32Bits());
1392   DCHECK(rn.Is64Bits());
1393   Emit(LDAR_h | Rs(x31) | Rt2(x31) | RnSP(rn) | Rt(rt));
1394 }
1395 
ldaxrh(const Register & rt,const Register & rn)1396 void Assembler::ldaxrh(const Register& rt, const Register& rn) {
1397   DCHECK(rt.Is32Bits());
1398   DCHECK(rn.Is64Bits());
1399   Emit(LDAXR_h | Rs(x31) | Rt2(x31) | RnSP(rn) | Rt(rt));
1400 }
1401 
stlrh(const Register & rt,const Register & rn)1402 void Assembler::stlrh(const Register& rt, const Register& rn) {
1403   DCHECK(rt.Is32Bits());
1404   DCHECK(rn.Is64Bits());
1405   Emit(STLR_h | Rs(x31) | Rt2(x31) | RnSP(rn) | Rt(rt));
1406 }
1407 
stlxrh(const Register & rs,const Register & rt,const Register & rn)1408 void Assembler::stlxrh(const Register& rs, const Register& rt,
1409                        const Register& rn) {
1410   DCHECK(rs.Is32Bits());
1411   DCHECK(rt.Is32Bits());
1412   DCHECK(rn.Is64Bits());
1413   DCHECK(rs != rt && rs != rn);
1414   Emit(STLXR_h | Rs(rs) | Rt2(x31) | RnSP(rn) | Rt(rt));
1415 }
1416 
NEON3DifferentL(const VRegister & vd,const VRegister & vn,const VRegister & vm,NEON3DifferentOp vop)1417 void Assembler::NEON3DifferentL(const VRegister& vd, const VRegister& vn,
1418                                 const VRegister& vm, NEON3DifferentOp vop) {
1419   DCHECK(AreSameFormat(vn, vm));
1420   DCHECK((vn.Is1H() && vd.Is1S()) || (vn.Is1S() && vd.Is1D()) ||
1421          (vn.Is8B() && vd.Is8H()) || (vn.Is4H() && vd.Is4S()) ||
1422          (vn.Is2S() && vd.Is2D()) || (vn.Is16B() && vd.Is8H()) ||
1423          (vn.Is8H() && vd.Is4S()) || (vn.Is4S() && vd.Is2D()));
1424   Instr format, op = vop;
1425   if (vd.IsScalar()) {
1426     op |= NEON_Q | NEONScalar;
1427     format = SFormat(vn);
1428   } else {
1429     format = VFormat(vn);
1430   }
1431   Emit(format | op | Rm(vm) | Rn(vn) | Rd(vd));
1432 }
1433 
NEON3DifferentW(const VRegister & vd,const VRegister & vn,const VRegister & vm,NEON3DifferentOp vop)1434 void Assembler::NEON3DifferentW(const VRegister& vd, const VRegister& vn,
1435                                 const VRegister& vm, NEON3DifferentOp vop) {
1436   DCHECK(AreSameFormat(vd, vn));
1437   DCHECK((vm.Is8B() && vd.Is8H()) || (vm.Is4H() && vd.Is4S()) ||
1438          (vm.Is2S() && vd.Is2D()) || (vm.Is16B() && vd.Is8H()) ||
1439          (vm.Is8H() && vd.Is4S()) || (vm.Is4S() && vd.Is2D()));
1440   Emit(VFormat(vm) | vop | Rm(vm) | Rn(vn) | Rd(vd));
1441 }
1442 
NEON3DifferentHN(const VRegister & vd,const VRegister & vn,const VRegister & vm,NEON3DifferentOp vop)1443 void Assembler::NEON3DifferentHN(const VRegister& vd, const VRegister& vn,
1444                                  const VRegister& vm, NEON3DifferentOp vop) {
1445   DCHECK(AreSameFormat(vm, vn));
1446   DCHECK((vd.Is8B() && vn.Is8H()) || (vd.Is4H() && vn.Is4S()) ||
1447          (vd.Is2S() && vn.Is2D()) || (vd.Is16B() && vn.Is8H()) ||
1448          (vd.Is8H() && vn.Is4S()) || (vd.Is4S() && vn.Is2D()));
1449   Emit(VFormat(vd) | vop | Rm(vm) | Rn(vn) | Rd(vd));
1450 }
1451 
1452 #define NEON_3DIFF_LONG_LIST(V)                                                \
1453   V(pmull, NEON_PMULL, vn.IsVector() && vn.Is8B())                             \
1454   V(pmull2, NEON_PMULL2, vn.IsVector() && vn.Is16B())                          \
1455   V(saddl, NEON_SADDL, vn.IsVector() && vn.IsD())                              \
1456   V(saddl2, NEON_SADDL2, vn.IsVector() && vn.IsQ())                            \
1457   V(sabal, NEON_SABAL, vn.IsVector() && vn.IsD())                              \
1458   V(sabal2, NEON_SABAL2, vn.IsVector() && vn.IsQ())                            \
1459   V(uabal, NEON_UABAL, vn.IsVector() && vn.IsD())                              \
1460   V(uabal2, NEON_UABAL2, vn.IsVector() && vn.IsQ())                            \
1461   V(sabdl, NEON_SABDL, vn.IsVector() && vn.IsD())                              \
1462   V(sabdl2, NEON_SABDL2, vn.IsVector() && vn.IsQ())                            \
1463   V(uabdl, NEON_UABDL, vn.IsVector() && vn.IsD())                              \
1464   V(uabdl2, NEON_UABDL2, vn.IsVector() && vn.IsQ())                            \
1465   V(smlal, NEON_SMLAL, vn.IsVector() && vn.IsD())                              \
1466   V(smlal2, NEON_SMLAL2, vn.IsVector() && vn.IsQ())                            \
1467   V(umlal, NEON_UMLAL, vn.IsVector() && vn.IsD())                              \
1468   V(umlal2, NEON_UMLAL2, vn.IsVector() && vn.IsQ())                            \
1469   V(smlsl, NEON_SMLSL, vn.IsVector() && vn.IsD())                              \
1470   V(smlsl2, NEON_SMLSL2, vn.IsVector() && vn.IsQ())                            \
1471   V(umlsl, NEON_UMLSL, vn.IsVector() && vn.IsD())                              \
1472   V(umlsl2, NEON_UMLSL2, vn.IsVector() && vn.IsQ())                            \
1473   V(smull, NEON_SMULL, vn.IsVector() && vn.IsD())                              \
1474   V(smull2, NEON_SMULL2, vn.IsVector() && vn.IsQ())                            \
1475   V(umull, NEON_UMULL, vn.IsVector() && vn.IsD())                              \
1476   V(umull2, NEON_UMULL2, vn.IsVector() && vn.IsQ())                            \
1477   V(ssubl, NEON_SSUBL, vn.IsVector() && vn.IsD())                              \
1478   V(ssubl2, NEON_SSUBL2, vn.IsVector() && vn.IsQ())                            \
1479   V(uaddl, NEON_UADDL, vn.IsVector() && vn.IsD())                              \
1480   V(uaddl2, NEON_UADDL2, vn.IsVector() && vn.IsQ())                            \
1481   V(usubl, NEON_USUBL, vn.IsVector() && vn.IsD())                              \
1482   V(usubl2, NEON_USUBL2, vn.IsVector() && vn.IsQ())                            \
1483   V(sqdmlal, NEON_SQDMLAL, vn.Is1H() || vn.Is1S() || vn.Is4H() || vn.Is2S())   \
1484   V(sqdmlal2, NEON_SQDMLAL2, vn.Is1H() || vn.Is1S() || vn.Is8H() || vn.Is4S()) \
1485   V(sqdmlsl, NEON_SQDMLSL, vn.Is1H() || vn.Is1S() || vn.Is4H() || vn.Is2S())   \
1486   V(sqdmlsl2, NEON_SQDMLSL2, vn.Is1H() || vn.Is1S() || vn.Is8H() || vn.Is4S()) \
1487   V(sqdmull, NEON_SQDMULL, vn.Is1H() || vn.Is1S() || vn.Is4H() || vn.Is2S())   \
1488   V(sqdmull2, NEON_SQDMULL2, vn.Is1H() || vn.Is1S() || vn.Is8H() || vn.Is4S())
1489 
1490 #define DEFINE_ASM_FUNC(FN, OP, AS)                            \
1491   void Assembler::FN(const VRegister& vd, const VRegister& vn, \
1492                      const VRegister& vm) {                    \
1493     DCHECK(AS);                                                \
1494     NEON3DifferentL(vd, vn, vm, OP);                           \
1495   }
1496 NEON_3DIFF_LONG_LIST(DEFINE_ASM_FUNC)
1497 #undef DEFINE_ASM_FUNC
1498 
1499 #define NEON_3DIFF_HN_LIST(V)        \
1500   V(addhn, NEON_ADDHN, vd.IsD())     \
1501   V(addhn2, NEON_ADDHN2, vd.IsQ())   \
1502   V(raddhn, NEON_RADDHN, vd.IsD())   \
1503   V(raddhn2, NEON_RADDHN2, vd.IsQ()) \
1504   V(subhn, NEON_SUBHN, vd.IsD())     \
1505   V(subhn2, NEON_SUBHN2, vd.IsQ())   \
1506   V(rsubhn, NEON_RSUBHN, vd.IsD())   \
1507   V(rsubhn2, NEON_RSUBHN2, vd.IsQ())
1508 
1509 #define DEFINE_ASM_FUNC(FN, OP, AS)                            \
1510   void Assembler::FN(const VRegister& vd, const VRegister& vn, \
1511                      const VRegister& vm) {                    \
1512     DCHECK(AS);                                                \
1513     NEON3DifferentHN(vd, vn, vm, OP);                          \
1514   }
NEON_3DIFF_HN_LIST(DEFINE_ASM_FUNC)1515 NEON_3DIFF_HN_LIST(DEFINE_ASM_FUNC)
1516 #undef DEFINE_ASM_FUNC
1517 
1518 void Assembler::NEONPerm(const VRegister& vd, const VRegister& vn,
1519                          const VRegister& vm, NEONPermOp op) {
1520   DCHECK(AreSameFormat(vd, vn, vm));
1521   DCHECK(!vd.Is1D());
1522   Emit(VFormat(vd) | op | Rm(vm) | Rn(vn) | Rd(vd));
1523 }
1524 
trn1(const VRegister & vd,const VRegister & vn,const VRegister & vm)1525 void Assembler::trn1(const VRegister& vd, const VRegister& vn,
1526                      const VRegister& vm) {
1527   NEONPerm(vd, vn, vm, NEON_TRN1);
1528 }
1529 
trn2(const VRegister & vd,const VRegister & vn,const VRegister & vm)1530 void Assembler::trn2(const VRegister& vd, const VRegister& vn,
1531                      const VRegister& vm) {
1532   NEONPerm(vd, vn, vm, NEON_TRN2);
1533 }
1534 
uzp1(const VRegister & vd,const VRegister & vn,const VRegister & vm)1535 void Assembler::uzp1(const VRegister& vd, const VRegister& vn,
1536                      const VRegister& vm) {
1537   NEONPerm(vd, vn, vm, NEON_UZP1);
1538 }
1539 
uzp2(const VRegister & vd,const VRegister & vn,const VRegister & vm)1540 void Assembler::uzp2(const VRegister& vd, const VRegister& vn,
1541                      const VRegister& vm) {
1542   NEONPerm(vd, vn, vm, NEON_UZP2);
1543 }
1544 
zip1(const VRegister & vd,const VRegister & vn,const VRegister & vm)1545 void Assembler::zip1(const VRegister& vd, const VRegister& vn,
1546                      const VRegister& vm) {
1547   NEONPerm(vd, vn, vm, NEON_ZIP1);
1548 }
1549 
zip2(const VRegister & vd,const VRegister & vn,const VRegister & vm)1550 void Assembler::zip2(const VRegister& vd, const VRegister& vn,
1551                      const VRegister& vm) {
1552   NEONPerm(vd, vn, vm, NEON_ZIP2);
1553 }
1554 
NEONShiftImmediate(const VRegister & vd,const VRegister & vn,NEONShiftImmediateOp op,int immh_immb)1555 void Assembler::NEONShiftImmediate(const VRegister& vd, const VRegister& vn,
1556                                    NEONShiftImmediateOp op, int immh_immb) {
1557   DCHECK(AreSameFormat(vd, vn));
1558   Instr q, scalar;
1559   if (vn.IsScalar()) {
1560     q = NEON_Q;
1561     scalar = NEONScalar;
1562   } else {
1563     q = vd.IsD() ? 0 : NEON_Q;
1564     scalar = 0;
1565   }
1566   Emit(q | op | scalar | immh_immb | Rn(vn) | Rd(vd));
1567 }
1568 
NEONShiftLeftImmediate(const VRegister & vd,const VRegister & vn,int shift,NEONShiftImmediateOp op)1569 void Assembler::NEONShiftLeftImmediate(const VRegister& vd, const VRegister& vn,
1570                                        int shift, NEONShiftImmediateOp op) {
1571   int laneSizeInBits = vn.LaneSizeInBits();
1572   DCHECK((shift >= 0) && (shift < laneSizeInBits));
1573   NEONShiftImmediate(vd, vn, op, (laneSizeInBits + shift) << 16);
1574 }
1575 
NEONShiftRightImmediate(const VRegister & vd,const VRegister & vn,int shift,NEONShiftImmediateOp op)1576 void Assembler::NEONShiftRightImmediate(const VRegister& vd,
1577                                         const VRegister& vn, int shift,
1578                                         NEONShiftImmediateOp op) {
1579   int laneSizeInBits = vn.LaneSizeInBits();
1580   DCHECK((shift >= 1) && (shift <= laneSizeInBits));
1581   NEONShiftImmediate(vd, vn, op, ((2 * laneSizeInBits) - shift) << 16);
1582 }
1583 
NEONShiftImmediateL(const VRegister & vd,const VRegister & vn,int shift,NEONShiftImmediateOp op)1584 void Assembler::NEONShiftImmediateL(const VRegister& vd, const VRegister& vn,
1585                                     int shift, NEONShiftImmediateOp op) {
1586   int laneSizeInBits = vn.LaneSizeInBits();
1587   DCHECK((shift >= 0) && (shift < laneSizeInBits));
1588   int immh_immb = (laneSizeInBits + shift) << 16;
1589 
1590   DCHECK((vn.Is8B() && vd.Is8H()) || (vn.Is4H() && vd.Is4S()) ||
1591          (vn.Is2S() && vd.Is2D()) || (vn.Is16B() && vd.Is8H()) ||
1592          (vn.Is8H() && vd.Is4S()) || (vn.Is4S() && vd.Is2D()));
1593   Instr q;
1594   q = vn.IsD() ? 0 : NEON_Q;
1595   Emit(q | op | immh_immb | Rn(vn) | Rd(vd));
1596 }
1597 
NEONShiftImmediateN(const VRegister & vd,const VRegister & vn,int shift,NEONShiftImmediateOp op)1598 void Assembler::NEONShiftImmediateN(const VRegister& vd, const VRegister& vn,
1599                                     int shift, NEONShiftImmediateOp op) {
1600   Instr q, scalar;
1601   int laneSizeInBits = vd.LaneSizeInBits();
1602   DCHECK((shift >= 1) && (shift <= laneSizeInBits));
1603   int immh_immb = (2 * laneSizeInBits - shift) << 16;
1604 
1605   if (vn.IsScalar()) {
1606     DCHECK((vd.Is1B() && vn.Is1H()) || (vd.Is1H() && vn.Is1S()) ||
1607            (vd.Is1S() && vn.Is1D()));
1608     q = NEON_Q;
1609     scalar = NEONScalar;
1610   } else {
1611     DCHECK((vd.Is8B() && vn.Is8H()) || (vd.Is4H() && vn.Is4S()) ||
1612            (vd.Is2S() && vn.Is2D()) || (vd.Is16B() && vn.Is8H()) ||
1613            (vd.Is8H() && vn.Is4S()) || (vd.Is4S() && vn.Is2D()));
1614     scalar = 0;
1615     q = vd.IsD() ? 0 : NEON_Q;
1616   }
1617   Emit(q | op | scalar | immh_immb | Rn(vn) | Rd(vd));
1618 }
1619 
shl(const VRegister & vd,const VRegister & vn,int shift)1620 void Assembler::shl(const VRegister& vd, const VRegister& vn, int shift) {
1621   DCHECK(vd.IsVector() || vd.Is1D());
1622   NEONShiftLeftImmediate(vd, vn, shift, NEON_SHL);
1623 }
1624 
sli(const VRegister & vd,const VRegister & vn,int shift)1625 void Assembler::sli(const VRegister& vd, const VRegister& vn, int shift) {
1626   DCHECK(vd.IsVector() || vd.Is1D());
1627   NEONShiftLeftImmediate(vd, vn, shift, NEON_SLI);
1628 }
1629 
sqshl(const VRegister & vd,const VRegister & vn,int shift)1630 void Assembler::sqshl(const VRegister& vd, const VRegister& vn, int shift) {
1631   NEONShiftLeftImmediate(vd, vn, shift, NEON_SQSHL_imm);
1632 }
1633 
sqshlu(const VRegister & vd,const VRegister & vn,int shift)1634 void Assembler::sqshlu(const VRegister& vd, const VRegister& vn, int shift) {
1635   NEONShiftLeftImmediate(vd, vn, shift, NEON_SQSHLU);
1636 }
1637 
uqshl(const VRegister & vd,const VRegister & vn,int shift)1638 void Assembler::uqshl(const VRegister& vd, const VRegister& vn, int shift) {
1639   NEONShiftLeftImmediate(vd, vn, shift, NEON_UQSHL_imm);
1640 }
1641 
sshll(const VRegister & vd,const VRegister & vn,int shift)1642 void Assembler::sshll(const VRegister& vd, const VRegister& vn, int shift) {
1643   DCHECK(vn.IsD());
1644   NEONShiftImmediateL(vd, vn, shift, NEON_SSHLL);
1645 }
1646 
sshll2(const VRegister & vd,const VRegister & vn,int shift)1647 void Assembler::sshll2(const VRegister& vd, const VRegister& vn, int shift) {
1648   DCHECK(vn.IsQ());
1649   NEONShiftImmediateL(vd, vn, shift, NEON_SSHLL);
1650 }
1651 
sxtl(const VRegister & vd,const VRegister & vn)1652 void Assembler::sxtl(const VRegister& vd, const VRegister& vn) {
1653   sshll(vd, vn, 0);
1654 }
1655 
sxtl2(const VRegister & vd,const VRegister & vn)1656 void Assembler::sxtl2(const VRegister& vd, const VRegister& vn) {
1657   sshll2(vd, vn, 0);
1658 }
1659 
ushll(const VRegister & vd,const VRegister & vn,int shift)1660 void Assembler::ushll(const VRegister& vd, const VRegister& vn, int shift) {
1661   DCHECK(vn.IsD());
1662   NEONShiftImmediateL(vd, vn, shift, NEON_USHLL);
1663 }
1664 
ushll2(const VRegister & vd,const VRegister & vn,int shift)1665 void Assembler::ushll2(const VRegister& vd, const VRegister& vn, int shift) {
1666   DCHECK(vn.IsQ());
1667   NEONShiftImmediateL(vd, vn, shift, NEON_USHLL);
1668 }
1669 
uxtl(const VRegister & vd,const VRegister & vn)1670 void Assembler::uxtl(const VRegister& vd, const VRegister& vn) {
1671   ushll(vd, vn, 0);
1672 }
1673 
uxtl2(const VRegister & vd,const VRegister & vn)1674 void Assembler::uxtl2(const VRegister& vd, const VRegister& vn) {
1675   ushll2(vd, vn, 0);
1676 }
1677 
sri(const VRegister & vd,const VRegister & vn,int shift)1678 void Assembler::sri(const VRegister& vd, const VRegister& vn, int shift) {
1679   DCHECK(vd.IsVector() || vd.Is1D());
1680   NEONShiftRightImmediate(vd, vn, shift, NEON_SRI);
1681 }
1682 
sshr(const VRegister & vd,const VRegister & vn,int shift)1683 void Assembler::sshr(const VRegister& vd, const VRegister& vn, int shift) {
1684   DCHECK(vd.IsVector() || vd.Is1D());
1685   NEONShiftRightImmediate(vd, vn, shift, NEON_SSHR);
1686 }
1687 
ushr(const VRegister & vd,const VRegister & vn,int shift)1688 void Assembler::ushr(const VRegister& vd, const VRegister& vn, int shift) {
1689   DCHECK(vd.IsVector() || vd.Is1D());
1690   NEONShiftRightImmediate(vd, vn, shift, NEON_USHR);
1691 }
1692 
srshr(const VRegister & vd,const VRegister & vn,int shift)1693 void Assembler::srshr(const VRegister& vd, const VRegister& vn, int shift) {
1694   DCHECK(vd.IsVector() || vd.Is1D());
1695   NEONShiftRightImmediate(vd, vn, shift, NEON_SRSHR);
1696 }
1697 
urshr(const VRegister & vd,const VRegister & vn,int shift)1698 void Assembler::urshr(const VRegister& vd, const VRegister& vn, int shift) {
1699   DCHECK(vd.IsVector() || vd.Is1D());
1700   NEONShiftRightImmediate(vd, vn, shift, NEON_URSHR);
1701 }
1702 
ssra(const VRegister & vd,const VRegister & vn,int shift)1703 void Assembler::ssra(const VRegister& vd, const VRegister& vn, int shift) {
1704   DCHECK(vd.IsVector() || vd.Is1D());
1705   NEONShiftRightImmediate(vd, vn, shift, NEON_SSRA);
1706 }
1707 
usra(const VRegister & vd,const VRegister & vn,int shift)1708 void Assembler::usra(const VRegister& vd, const VRegister& vn, int shift) {
1709   DCHECK(vd.IsVector() || vd.Is1D());
1710   NEONShiftRightImmediate(vd, vn, shift, NEON_USRA);
1711 }
1712 
srsra(const VRegister & vd,const VRegister & vn,int shift)1713 void Assembler::srsra(const VRegister& vd, const VRegister& vn, int shift) {
1714   DCHECK(vd.IsVector() || vd.Is1D());
1715   NEONShiftRightImmediate(vd, vn, shift, NEON_SRSRA);
1716 }
1717 
ursra(const VRegister & vd,const VRegister & vn,int shift)1718 void Assembler::ursra(const VRegister& vd, const VRegister& vn, int shift) {
1719   DCHECK(vd.IsVector() || vd.Is1D());
1720   NEONShiftRightImmediate(vd, vn, shift, NEON_URSRA);
1721 }
1722 
shrn(const VRegister & vd,const VRegister & vn,int shift)1723 void Assembler::shrn(const VRegister& vd, const VRegister& vn, int shift) {
1724   DCHECK(vn.IsVector() && vd.IsD());
1725   NEONShiftImmediateN(vd, vn, shift, NEON_SHRN);
1726 }
1727 
shrn2(const VRegister & vd,const VRegister & vn,int shift)1728 void Assembler::shrn2(const VRegister& vd, const VRegister& vn, int shift) {
1729   DCHECK(vn.IsVector() && vd.IsQ());
1730   NEONShiftImmediateN(vd, vn, shift, NEON_SHRN);
1731 }
1732 
rshrn(const VRegister & vd,const VRegister & vn,int shift)1733 void Assembler::rshrn(const VRegister& vd, const VRegister& vn, int shift) {
1734   DCHECK(vn.IsVector() && vd.IsD());
1735   NEONShiftImmediateN(vd, vn, shift, NEON_RSHRN);
1736 }
1737 
rshrn2(const VRegister & vd,const VRegister & vn,int shift)1738 void Assembler::rshrn2(const VRegister& vd, const VRegister& vn, int shift) {
1739   DCHECK(vn.IsVector() && vd.IsQ());
1740   NEONShiftImmediateN(vd, vn, shift, NEON_RSHRN);
1741 }
1742 
sqshrn(const VRegister & vd,const VRegister & vn,int shift)1743 void Assembler::sqshrn(const VRegister& vd, const VRegister& vn, int shift) {
1744   DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
1745   NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRN);
1746 }
1747 
sqshrn2(const VRegister & vd,const VRegister & vn,int shift)1748 void Assembler::sqshrn2(const VRegister& vd, const VRegister& vn, int shift) {
1749   DCHECK(vn.IsVector() && vd.IsQ());
1750   NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRN);
1751 }
1752 
sqrshrn(const VRegister & vd,const VRegister & vn,int shift)1753 void Assembler::sqrshrn(const VRegister& vd, const VRegister& vn, int shift) {
1754   DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
1755   NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRN);
1756 }
1757 
sqrshrn2(const VRegister & vd,const VRegister & vn,int shift)1758 void Assembler::sqrshrn2(const VRegister& vd, const VRegister& vn, int shift) {
1759   DCHECK(vn.IsVector() && vd.IsQ());
1760   NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRN);
1761 }
1762 
sqshrun(const VRegister & vd,const VRegister & vn,int shift)1763 void Assembler::sqshrun(const VRegister& vd, const VRegister& vn, int shift) {
1764   DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
1765   NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRUN);
1766 }
1767 
sqshrun2(const VRegister & vd,const VRegister & vn,int shift)1768 void Assembler::sqshrun2(const VRegister& vd, const VRegister& vn, int shift) {
1769   DCHECK(vn.IsVector() && vd.IsQ());
1770   NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRUN);
1771 }
1772 
sqrshrun(const VRegister & vd,const VRegister & vn,int shift)1773 void Assembler::sqrshrun(const VRegister& vd, const VRegister& vn, int shift) {
1774   DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
1775   NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRUN);
1776 }
1777 
sqrshrun2(const VRegister & vd,const VRegister & vn,int shift)1778 void Assembler::sqrshrun2(const VRegister& vd, const VRegister& vn, int shift) {
1779   DCHECK(vn.IsVector() && vd.IsQ());
1780   NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRUN);
1781 }
1782 
uqshrn(const VRegister & vd,const VRegister & vn,int shift)1783 void Assembler::uqshrn(const VRegister& vd, const VRegister& vn, int shift) {
1784   DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
1785   NEONShiftImmediateN(vd, vn, shift, NEON_UQSHRN);
1786 }
1787 
uqshrn2(const VRegister & vd,const VRegister & vn,int shift)1788 void Assembler::uqshrn2(const VRegister& vd, const VRegister& vn, int shift) {
1789   DCHECK(vn.IsVector() && vd.IsQ());
1790   NEONShiftImmediateN(vd, vn, shift, NEON_UQSHRN);
1791 }
1792 
uqrshrn(const VRegister & vd,const VRegister & vn,int shift)1793 void Assembler::uqrshrn(const VRegister& vd, const VRegister& vn, int shift) {
1794   DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
1795   NEONShiftImmediateN(vd, vn, shift, NEON_UQRSHRN);
1796 }
1797 
uqrshrn2(const VRegister & vd,const VRegister & vn,int shift)1798 void Assembler::uqrshrn2(const VRegister& vd, const VRegister& vn, int shift) {
1799   DCHECK(vn.IsVector() && vd.IsQ());
1800   NEONShiftImmediateN(vd, vn, shift, NEON_UQRSHRN);
1801 }
1802 
uaddw(const VRegister & vd,const VRegister & vn,const VRegister & vm)1803 void Assembler::uaddw(const VRegister& vd, const VRegister& vn,
1804                       const VRegister& vm) {
1805   DCHECK(vm.IsD());
1806   NEON3DifferentW(vd, vn, vm, NEON_UADDW);
1807 }
1808 
uaddw2(const VRegister & vd,const VRegister & vn,const VRegister & vm)1809 void Assembler::uaddw2(const VRegister& vd, const VRegister& vn,
1810                        const VRegister& vm) {
1811   DCHECK(vm.IsQ());
1812   NEON3DifferentW(vd, vn, vm, NEON_UADDW2);
1813 }
1814 
saddw(const VRegister & vd,const VRegister & vn,const VRegister & vm)1815 void Assembler::saddw(const VRegister& vd, const VRegister& vn,
1816                       const VRegister& vm) {
1817   DCHECK(vm.IsD());
1818   NEON3DifferentW(vd, vn, vm, NEON_SADDW);
1819 }
1820 
saddw2(const VRegister & vd,const VRegister & vn,const VRegister & vm)1821 void Assembler::saddw2(const VRegister& vd, const VRegister& vn,
1822                        const VRegister& vm) {
1823   DCHECK(vm.IsQ());
1824   NEON3DifferentW(vd, vn, vm, NEON_SADDW2);
1825 }
1826 
usubw(const VRegister & vd,const VRegister & vn,const VRegister & vm)1827 void Assembler::usubw(const VRegister& vd, const VRegister& vn,
1828                       const VRegister& vm) {
1829   DCHECK(vm.IsD());
1830   NEON3DifferentW(vd, vn, vm, NEON_USUBW);
1831 }
1832 
usubw2(const VRegister & vd,const VRegister & vn,const VRegister & vm)1833 void Assembler::usubw2(const VRegister& vd, const VRegister& vn,
1834                        const VRegister& vm) {
1835   DCHECK(vm.IsQ());
1836   NEON3DifferentW(vd, vn, vm, NEON_USUBW2);
1837 }
1838 
ssubw(const VRegister & vd,const VRegister & vn,const VRegister & vm)1839 void Assembler::ssubw(const VRegister& vd, const VRegister& vn,
1840                       const VRegister& vm) {
1841   DCHECK(vm.IsD());
1842   NEON3DifferentW(vd, vn, vm, NEON_SSUBW);
1843 }
1844 
ssubw2(const VRegister & vd,const VRegister & vn,const VRegister & vm)1845 void Assembler::ssubw2(const VRegister& vd, const VRegister& vn,
1846                        const VRegister& vm) {
1847   DCHECK(vm.IsQ());
1848   NEON3DifferentW(vd, vn, vm, NEON_SSUBW2);
1849 }
1850 
mov(const Register & rd,const Register & rm)1851 void Assembler::mov(const Register& rd, const Register& rm) {
1852   // Moves involving the stack pointer are encoded as add immediate with
1853   // second operand of zero. Otherwise, orr with first operand zr is
1854   // used.
1855   if (rd.IsSP() || rm.IsSP()) {
1856     add(rd, rm, 0);
1857   } else {
1858     orr(rd, AppropriateZeroRegFor(rd), rm);
1859   }
1860 }
1861 
ins(const VRegister & vd,int vd_index,const Register & rn)1862 void Assembler::ins(const VRegister& vd, int vd_index, const Register& rn) {
1863   // We support vd arguments of the form vd.VxT() or vd.T(), where x is the
1864   // number of lanes, and T is b, h, s or d.
1865   int lane_size = vd.LaneSizeInBytes();
1866   NEONFormatField format;
1867   switch (lane_size) {
1868     case 1:
1869       format = NEON_16B;
1870       DCHECK(rn.IsW());
1871       break;
1872     case 2:
1873       format = NEON_8H;
1874       DCHECK(rn.IsW());
1875       break;
1876     case 4:
1877       format = NEON_4S;
1878       DCHECK(rn.IsW());
1879       break;
1880     default:
1881       DCHECK_EQ(lane_size, 8);
1882       DCHECK(rn.IsX());
1883       format = NEON_2D;
1884       break;
1885   }
1886 
1887   DCHECK((0 <= vd_index) &&
1888          (vd_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
1889   Emit(NEON_INS_GENERAL | ImmNEON5(format, vd_index) | Rn(rn) | Rd(vd));
1890 }
1891 
mov(const Register & rd,const VRegister & vn,int vn_index)1892 void Assembler::mov(const Register& rd, const VRegister& vn, int vn_index) {
1893   DCHECK_GE(vn.SizeInBytes(), 4);
1894   umov(rd, vn, vn_index);
1895 }
1896 
smov(const Register & rd,const VRegister & vn,int vn_index)1897 void Assembler::smov(const Register& rd, const VRegister& vn, int vn_index) {
1898   // We support vn arguments of the form vn.VxT() or vn.T(), where x is the
1899   // number of lanes, and T is b, h, s.
1900   int lane_size = vn.LaneSizeInBytes();
1901   NEONFormatField format;
1902   Instr q = 0;
1903   switch (lane_size) {
1904     case 1:
1905       format = NEON_16B;
1906       break;
1907     case 2:
1908       format = NEON_8H;
1909       break;
1910     default:
1911       DCHECK_EQ(lane_size, 4);
1912       DCHECK(rd.IsX());
1913       format = NEON_4S;
1914       break;
1915   }
1916   q = rd.IsW() ? 0 : NEON_Q;
1917   DCHECK((0 <= vn_index) &&
1918          (vn_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
1919   Emit(q | NEON_SMOV | ImmNEON5(format, vn_index) | Rn(vn) | Rd(rd));
1920 }
1921 
cls(const VRegister & vd,const VRegister & vn)1922 void Assembler::cls(const VRegister& vd, const VRegister& vn) {
1923   DCHECK(AreSameFormat(vd, vn));
1924   DCHECK(!vd.Is1D() && !vd.Is2D());
1925   Emit(VFormat(vn) | NEON_CLS | Rn(vn) | Rd(vd));
1926 }
1927 
clz(const VRegister & vd,const VRegister & vn)1928 void Assembler::clz(const VRegister& vd, const VRegister& vn) {
1929   DCHECK(AreSameFormat(vd, vn));
1930   DCHECK(!vd.Is1D() && !vd.Is2D());
1931   Emit(VFormat(vn) | NEON_CLZ | Rn(vn) | Rd(vd));
1932 }
1933 
cnt(const VRegister & vd,const VRegister & vn)1934 void Assembler::cnt(const VRegister& vd, const VRegister& vn) {
1935   DCHECK(AreSameFormat(vd, vn));
1936   DCHECK(vd.Is8B() || vd.Is16B());
1937   Emit(VFormat(vn) | NEON_CNT | Rn(vn) | Rd(vd));
1938 }
1939 
rev16(const VRegister & vd,const VRegister & vn)1940 void Assembler::rev16(const VRegister& vd, const VRegister& vn) {
1941   DCHECK(AreSameFormat(vd, vn));
1942   DCHECK(vd.Is8B() || vd.Is16B());
1943   Emit(VFormat(vn) | NEON_REV16 | Rn(vn) | Rd(vd));
1944 }
1945 
rev32(const VRegister & vd,const VRegister & vn)1946 void Assembler::rev32(const VRegister& vd, const VRegister& vn) {
1947   DCHECK(AreSameFormat(vd, vn));
1948   DCHECK(vd.Is8B() || vd.Is16B() || vd.Is4H() || vd.Is8H());
1949   Emit(VFormat(vn) | NEON_REV32 | Rn(vn) | Rd(vd));
1950 }
1951 
rev64(const VRegister & vd,const VRegister & vn)1952 void Assembler::rev64(const VRegister& vd, const VRegister& vn) {
1953   DCHECK(AreSameFormat(vd, vn));
1954   DCHECK(!vd.Is1D() && !vd.Is2D());
1955   Emit(VFormat(vn) | NEON_REV64 | Rn(vn) | Rd(vd));
1956 }
1957 
ursqrte(const VRegister & vd,const VRegister & vn)1958 void Assembler::ursqrte(const VRegister& vd, const VRegister& vn) {
1959   DCHECK(AreSameFormat(vd, vn));
1960   DCHECK(vd.Is2S() || vd.Is4S());
1961   Emit(VFormat(vn) | NEON_URSQRTE | Rn(vn) | Rd(vd));
1962 }
1963 
urecpe(const VRegister & vd,const VRegister & vn)1964 void Assembler::urecpe(const VRegister& vd, const VRegister& vn) {
1965   DCHECK(AreSameFormat(vd, vn));
1966   DCHECK(vd.Is2S() || vd.Is4S());
1967   Emit(VFormat(vn) | NEON_URECPE | Rn(vn) | Rd(vd));
1968 }
1969 
NEONAddlp(const VRegister & vd,const VRegister & vn,NEON2RegMiscOp op)1970 void Assembler::NEONAddlp(const VRegister& vd, const VRegister& vn,
1971                           NEON2RegMiscOp op) {
1972   DCHECK((op == NEON_SADDLP) || (op == NEON_UADDLP) || (op == NEON_SADALP) ||
1973          (op == NEON_UADALP));
1974 
1975   DCHECK((vn.Is8B() && vd.Is4H()) || (vn.Is4H() && vd.Is2S()) ||
1976          (vn.Is2S() && vd.Is1D()) || (vn.Is16B() && vd.Is8H()) ||
1977          (vn.Is8H() && vd.Is4S()) || (vn.Is4S() && vd.Is2D()));
1978   Emit(VFormat(vn) | op | Rn(vn) | Rd(vd));
1979 }
1980 
saddlp(const VRegister & vd,const VRegister & vn)1981 void Assembler::saddlp(const VRegister& vd, const VRegister& vn) {
1982   NEONAddlp(vd, vn, NEON_SADDLP);
1983 }
1984 
uaddlp(const VRegister & vd,const VRegister & vn)1985 void Assembler::uaddlp(const VRegister& vd, const VRegister& vn) {
1986   NEONAddlp(vd, vn, NEON_UADDLP);
1987 }
1988 
sadalp(const VRegister & vd,const VRegister & vn)1989 void Assembler::sadalp(const VRegister& vd, const VRegister& vn) {
1990   NEONAddlp(vd, vn, NEON_SADALP);
1991 }
1992 
uadalp(const VRegister & vd,const VRegister & vn)1993 void Assembler::uadalp(const VRegister& vd, const VRegister& vn) {
1994   NEONAddlp(vd, vn, NEON_UADALP);
1995 }
1996 
NEONAcrossLanesL(const VRegister & vd,const VRegister & vn,NEONAcrossLanesOp op)1997 void Assembler::NEONAcrossLanesL(const VRegister& vd, const VRegister& vn,
1998                                  NEONAcrossLanesOp op) {
1999   DCHECK((vn.Is8B() && vd.Is1H()) || (vn.Is16B() && vd.Is1H()) ||
2000          (vn.Is4H() && vd.Is1S()) || (vn.Is8H() && vd.Is1S()) ||
2001          (vn.Is4S() && vd.Is1D()));
2002   Emit(VFormat(vn) | op | Rn(vn) | Rd(vd));
2003 }
2004 
saddlv(const VRegister & vd,const VRegister & vn)2005 void Assembler::saddlv(const VRegister& vd, const VRegister& vn) {
2006   NEONAcrossLanesL(vd, vn, NEON_SADDLV);
2007 }
2008 
uaddlv(const VRegister & vd,const VRegister & vn)2009 void Assembler::uaddlv(const VRegister& vd, const VRegister& vn) {
2010   NEONAcrossLanesL(vd, vn, NEON_UADDLV);
2011 }
2012 
NEONAcrossLanes(const VRegister & vd,const VRegister & vn,NEONAcrossLanesOp op)2013 void Assembler::NEONAcrossLanes(const VRegister& vd, const VRegister& vn,
2014                                 NEONAcrossLanesOp op) {
2015   DCHECK((vn.Is8B() && vd.Is1B()) || (vn.Is16B() && vd.Is1B()) ||
2016          (vn.Is4H() && vd.Is1H()) || (vn.Is8H() && vd.Is1H()) ||
2017          (vn.Is4S() && vd.Is1S()));
2018   if ((op & NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
2019     Emit(FPFormat(vn) | op | Rn(vn) | Rd(vd));
2020   } else {
2021     Emit(VFormat(vn) | op | Rn(vn) | Rd(vd));
2022   }
2023 }
2024 
2025 #define NEON_ACROSSLANES_LIST(V)      \
2026   V(fmaxv, NEON_FMAXV, vd.Is1S())     \
2027   V(fminv, NEON_FMINV, vd.Is1S())     \
2028   V(fmaxnmv, NEON_FMAXNMV, vd.Is1S()) \
2029   V(fminnmv, NEON_FMINNMV, vd.Is1S()) \
2030   V(addv, NEON_ADDV, true)            \
2031   V(smaxv, NEON_SMAXV, true)          \
2032   V(sminv, NEON_SMINV, true)          \
2033   V(umaxv, NEON_UMAXV, true)          \
2034   V(uminv, NEON_UMINV, true)
2035 
2036 #define DEFINE_ASM_FUNC(FN, OP, AS)                              \
2037   void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
2038     DCHECK(AS);                                                  \
2039     NEONAcrossLanes(vd, vn, OP);                                 \
2040   }
NEON_ACROSSLANES_LIST(DEFINE_ASM_FUNC)2041 NEON_ACROSSLANES_LIST(DEFINE_ASM_FUNC)
2042 #undef DEFINE_ASM_FUNC
2043 
2044 void Assembler::mov(const VRegister& vd, int vd_index, const Register& rn) {
2045   ins(vd, vd_index, rn);
2046 }
2047 
umov(const Register & rd,const VRegister & vn,int vn_index)2048 void Assembler::umov(const Register& rd, const VRegister& vn, int vn_index) {
2049   // We support vn arguments of the form vn.VxT() or vn.T(), where x is the
2050   // number of lanes, and T is b, h, s or d.
2051   int lane_size = vn.LaneSizeInBytes();
2052   NEONFormatField format;
2053   Instr q = 0;
2054   switch (lane_size) {
2055     case 1:
2056       format = NEON_16B;
2057       DCHECK(rd.IsW());
2058       break;
2059     case 2:
2060       format = NEON_8H;
2061       DCHECK(rd.IsW());
2062       break;
2063     case 4:
2064       format = NEON_4S;
2065       DCHECK(rd.IsW());
2066       break;
2067     default:
2068       DCHECK_EQ(lane_size, 8);
2069       DCHECK(rd.IsX());
2070       format = NEON_2D;
2071       q = NEON_Q;
2072       break;
2073   }
2074 
2075   DCHECK((0 <= vn_index) &&
2076          (vn_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
2077   Emit(q | NEON_UMOV | ImmNEON5(format, vn_index) | Rn(vn) | Rd(rd));
2078 }
2079 
mov(const VRegister & vd,const VRegister & vn,int vn_index)2080 void Assembler::mov(const VRegister& vd, const VRegister& vn, int vn_index) {
2081   DCHECK(vd.IsScalar());
2082   dup(vd, vn, vn_index);
2083 }
2084 
dup(const VRegister & vd,const Register & rn)2085 void Assembler::dup(const VRegister& vd, const Register& rn) {
2086   DCHECK(!vd.Is1D());
2087   DCHECK_EQ(vd.Is2D(), rn.IsX());
2088   Instr q = vd.IsD() ? 0 : NEON_Q;
2089   Emit(q | NEON_DUP_GENERAL | ImmNEON5(VFormat(vd), 0) | Rn(rn) | Rd(vd));
2090 }
2091 
ins(const VRegister & vd,int vd_index,const VRegister & vn,int vn_index)2092 void Assembler::ins(const VRegister& vd, int vd_index, const VRegister& vn,
2093                     int vn_index) {
2094   DCHECK(AreSameFormat(vd, vn));
2095   // We support vd arguments of the form vd.VxT() or vd.T(), where x is the
2096   // number of lanes, and T is b, h, s or d.
2097   int lane_size = vd.LaneSizeInBytes();
2098   NEONFormatField format;
2099   switch (lane_size) {
2100     case 1:
2101       format = NEON_16B;
2102       break;
2103     case 2:
2104       format = NEON_8H;
2105       break;
2106     case 4:
2107       format = NEON_4S;
2108       break;
2109     default:
2110       DCHECK_EQ(lane_size, 8);
2111       format = NEON_2D;
2112       break;
2113   }
2114 
2115   DCHECK((0 <= vd_index) &&
2116          (vd_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
2117   DCHECK((0 <= vn_index) &&
2118          (vn_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
2119   Emit(NEON_INS_ELEMENT | ImmNEON5(format, vd_index) |
2120        ImmNEON4(format, vn_index) | Rn(vn) | Rd(vd));
2121 }
2122 
NEONTable(const VRegister & vd,const VRegister & vn,const VRegister & vm,NEONTableOp op)2123 void Assembler::NEONTable(const VRegister& vd, const VRegister& vn,
2124                           const VRegister& vm, NEONTableOp op) {
2125   DCHECK(vd.Is16B() || vd.Is8B());
2126   DCHECK(vn.Is16B());
2127   DCHECK(AreSameFormat(vd, vm));
2128   Emit(op | (vd.IsQ() ? NEON_Q : 0) | Rm(vm) | Rn(vn) | Rd(vd));
2129 }
2130 
tbl(const VRegister & vd,const VRegister & vn,const VRegister & vm)2131 void Assembler::tbl(const VRegister& vd, const VRegister& vn,
2132                     const VRegister& vm) {
2133   NEONTable(vd, vn, vm, NEON_TBL_1v);
2134 }
2135 
tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vm)2136 void Assembler::tbl(const VRegister& vd, const VRegister& vn,
2137                     const VRegister& vn2, const VRegister& vm) {
2138   USE(vn2);
2139   DCHECK(AreSameFormat(vn, vn2));
2140   DCHECK(AreConsecutive(vn, vn2));
2141   NEONTable(vd, vn, vm, NEON_TBL_2v);
2142 }
2143 
tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vm)2144 void Assembler::tbl(const VRegister& vd, const VRegister& vn,
2145                     const VRegister& vn2, const VRegister& vn3,
2146                     const VRegister& vm) {
2147   USE(vn2);
2148   USE(vn3);
2149   DCHECK(AreSameFormat(vn, vn2, vn3));
2150   DCHECK(AreConsecutive(vn, vn2, vn3));
2151   NEONTable(vd, vn, vm, NEON_TBL_3v);
2152 }
2153 
tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vn4,const VRegister & vm)2154 void Assembler::tbl(const VRegister& vd, const VRegister& vn,
2155                     const VRegister& vn2, const VRegister& vn3,
2156                     const VRegister& vn4, const VRegister& vm) {
2157   USE(vn2);
2158   USE(vn3);
2159   USE(vn4);
2160   DCHECK(AreSameFormat(vn, vn2, vn3, vn4));
2161   DCHECK(AreConsecutive(vn, vn2, vn3, vn4));
2162   NEONTable(vd, vn, vm, NEON_TBL_4v);
2163 }
2164 
tbx(const VRegister & vd,const VRegister & vn,const VRegister & vm)2165 void Assembler::tbx(const VRegister& vd, const VRegister& vn,
2166                     const VRegister& vm) {
2167   NEONTable(vd, vn, vm, NEON_TBX_1v);
2168 }
2169 
tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vm)2170 void Assembler::tbx(const VRegister& vd, const VRegister& vn,
2171                     const VRegister& vn2, const VRegister& vm) {
2172   USE(vn2);
2173   DCHECK(AreSameFormat(vn, vn2));
2174   DCHECK(AreConsecutive(vn, vn2));
2175   NEONTable(vd, vn, vm, NEON_TBX_2v);
2176 }
2177 
tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vm)2178 void Assembler::tbx(const VRegister& vd, const VRegister& vn,
2179                     const VRegister& vn2, const VRegister& vn3,
2180                     const VRegister& vm) {
2181   USE(vn2);
2182   USE(vn3);
2183   DCHECK(AreSameFormat(vn, vn2, vn3));
2184   DCHECK(AreConsecutive(vn, vn2, vn3));
2185   NEONTable(vd, vn, vm, NEON_TBX_3v);
2186 }
2187 
tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vn4,const VRegister & vm)2188 void Assembler::tbx(const VRegister& vd, const VRegister& vn,
2189                     const VRegister& vn2, const VRegister& vn3,
2190                     const VRegister& vn4, const VRegister& vm) {
2191   USE(vn2);
2192   USE(vn3);
2193   USE(vn4);
2194   DCHECK(AreSameFormat(vn, vn2, vn3, vn4));
2195   DCHECK(AreConsecutive(vn, vn2, vn3, vn4));
2196   NEONTable(vd, vn, vm, NEON_TBX_4v);
2197 }
2198 
mov(const VRegister & vd,int vd_index,const VRegister & vn,int vn_index)2199 void Assembler::mov(const VRegister& vd, int vd_index, const VRegister& vn,
2200                     int vn_index) {
2201   ins(vd, vd_index, vn, vn_index);
2202 }
2203 
mvn(const Register & rd,const Operand & operand)2204 void Assembler::mvn(const Register& rd, const Operand& operand) {
2205   orn(rd, AppropriateZeroRegFor(rd), operand);
2206 }
2207 
mrs(const Register & rt,SystemRegister sysreg)2208 void Assembler::mrs(const Register& rt, SystemRegister sysreg) {
2209   DCHECK(rt.Is64Bits());
2210   Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt));
2211 }
2212 
msr(SystemRegister sysreg,const Register & rt)2213 void Assembler::msr(SystemRegister sysreg, const Register& rt) {
2214   DCHECK(rt.Is64Bits());
2215   Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg));
2216 }
2217 
hint(SystemHint code)2218 void Assembler::hint(SystemHint code) { Emit(HINT | ImmHint(code) | Rt(xzr)); }
2219 
2220 // NEON structure loads and stores.
LoadStoreStructAddrModeField(const MemOperand & addr)2221 Instr Assembler::LoadStoreStructAddrModeField(const MemOperand& addr) {
2222   Instr addr_field = RnSP(addr.base());
2223 
2224   if (addr.IsPostIndex()) {
2225     static_assert(NEONLoadStoreMultiStructPostIndex ==
2226                       static_cast<NEONLoadStoreMultiStructPostIndexOp>(
2227                           NEONLoadStoreSingleStructPostIndex),
2228                   "Opcodes must match for NEON post index memop.");
2229 
2230     addr_field |= NEONLoadStoreMultiStructPostIndex;
2231     if (addr.offset() == 0) {
2232       addr_field |= RmNot31(addr.regoffset());
2233     } else {
2234       // The immediate post index addressing mode is indicated by rm = 31.
2235       // The immediate is implied by the number of vector registers used.
2236       addr_field |= (0x1F << Rm_offset);
2237     }
2238   } else {
2239     DCHECK(addr.IsImmediateOffset() && (addr.offset() == 0));
2240   }
2241   return addr_field;
2242 }
2243 
LoadStoreStructVerify(const VRegister & vt,const MemOperand & addr,Instr op)2244 void Assembler::LoadStoreStructVerify(const VRegister& vt,
2245                                       const MemOperand& addr, Instr op) {
2246 #ifdef DEBUG
2247   // Assert that addressing mode is either offset (with immediate 0), post
2248   // index by immediate of the size of the register list, or post index by a
2249   // value in a core register.
2250   if (addr.IsImmediateOffset()) {
2251     DCHECK_EQ(addr.offset(), 0);
2252   } else {
2253     int offset = vt.SizeInBytes();
2254     switch (op) {
2255       case NEON_LD1_1v:
2256       case NEON_ST1_1v:
2257         offset *= 1;
2258         break;
2259       case NEONLoadStoreSingleStructLoad1:
2260       case NEONLoadStoreSingleStructStore1:
2261       case NEON_LD1R:
2262         offset = (offset / vt.LaneCount()) * 1;
2263         break;
2264 
2265       case NEON_LD1_2v:
2266       case NEON_ST1_2v:
2267       case NEON_LD2:
2268       case NEON_ST2:
2269         offset *= 2;
2270         break;
2271       case NEONLoadStoreSingleStructLoad2:
2272       case NEONLoadStoreSingleStructStore2:
2273       case NEON_LD2R:
2274         offset = (offset / vt.LaneCount()) * 2;
2275         break;
2276 
2277       case NEON_LD1_3v:
2278       case NEON_ST1_3v:
2279       case NEON_LD3:
2280       case NEON_ST3:
2281         offset *= 3;
2282         break;
2283       case NEONLoadStoreSingleStructLoad3:
2284       case NEONLoadStoreSingleStructStore3:
2285       case NEON_LD3R:
2286         offset = (offset / vt.LaneCount()) * 3;
2287         break;
2288 
2289       case NEON_LD1_4v:
2290       case NEON_ST1_4v:
2291       case NEON_LD4:
2292       case NEON_ST4:
2293         offset *= 4;
2294         break;
2295       case NEONLoadStoreSingleStructLoad4:
2296       case NEONLoadStoreSingleStructStore4:
2297       case NEON_LD4R:
2298         offset = (offset / vt.LaneCount()) * 4;
2299         break;
2300       default:
2301         UNREACHABLE();
2302     }
2303     DCHECK(addr.regoffset() != NoReg || addr.offset() == offset);
2304   }
2305 #else
2306   USE(vt);
2307   USE(addr);
2308   USE(op);
2309 #endif
2310 }
2311 
LoadStoreStruct(const VRegister & vt,const MemOperand & addr,NEONLoadStoreMultiStructOp op)2312 void Assembler::LoadStoreStruct(const VRegister& vt, const MemOperand& addr,
2313                                 NEONLoadStoreMultiStructOp op) {
2314   LoadStoreStructVerify(vt, addr, op);
2315   DCHECK(vt.IsVector() || vt.Is1D());
2316   Emit(op | LoadStoreStructAddrModeField(addr) | LSVFormat(vt) | Rt(vt));
2317 }
2318 
LoadStoreStructSingleAllLanes(const VRegister & vt,const MemOperand & addr,NEONLoadStoreSingleStructOp op)2319 void Assembler::LoadStoreStructSingleAllLanes(const VRegister& vt,
2320                                               const MemOperand& addr,
2321                                               NEONLoadStoreSingleStructOp op) {
2322   LoadStoreStructVerify(vt, addr, op);
2323   Emit(op | LoadStoreStructAddrModeField(addr) | LSVFormat(vt) | Rt(vt));
2324 }
2325 
ld1(const VRegister & vt,const MemOperand & src)2326 void Assembler::ld1(const VRegister& vt, const MemOperand& src) {
2327   LoadStoreStruct(vt, src, NEON_LD1_1v);
2328 }
2329 
ld1(const VRegister & vt,const VRegister & vt2,const MemOperand & src)2330 void Assembler::ld1(const VRegister& vt, const VRegister& vt2,
2331                     const MemOperand& src) {
2332   USE(vt2);
2333   DCHECK(AreSameFormat(vt, vt2));
2334   DCHECK(AreConsecutive(vt, vt2));
2335   LoadStoreStruct(vt, src, NEON_LD1_2v);
2336 }
2337 
ld1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)2338 void Assembler::ld1(const VRegister& vt, const VRegister& vt2,
2339                     const VRegister& vt3, const MemOperand& src) {
2340   USE(vt2);
2341   USE(vt3);
2342   DCHECK(AreSameFormat(vt, vt2, vt3));
2343   DCHECK(AreConsecutive(vt, vt2, vt3));
2344   LoadStoreStruct(vt, src, NEON_LD1_3v);
2345 }
2346 
ld1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)2347 void Assembler::ld1(const VRegister& vt, const VRegister& vt2,
2348                     const VRegister& vt3, const VRegister& vt4,
2349                     const MemOperand& src) {
2350   USE(vt2);
2351   USE(vt3);
2352   USE(vt4);
2353   DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2354   DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2355   LoadStoreStruct(vt, src, NEON_LD1_4v);
2356 }
2357 
ld2(const VRegister & vt,const VRegister & vt2,const MemOperand & src)2358 void Assembler::ld2(const VRegister& vt, const VRegister& vt2,
2359                     const MemOperand& src) {
2360   USE(vt2);
2361   DCHECK(AreSameFormat(vt, vt2));
2362   DCHECK(AreConsecutive(vt, vt2));
2363   LoadStoreStruct(vt, src, NEON_LD2);
2364 }
2365 
ld2(const VRegister & vt,const VRegister & vt2,int lane,const MemOperand & src)2366 void Assembler::ld2(const VRegister& vt, const VRegister& vt2, int lane,
2367                     const MemOperand& src) {
2368   USE(vt2);
2369   DCHECK(AreSameFormat(vt, vt2));
2370   DCHECK(AreConsecutive(vt, vt2));
2371   LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad2);
2372 }
2373 
ld2r(const VRegister & vt,const VRegister & vt2,const MemOperand & src)2374 void Assembler::ld2r(const VRegister& vt, const VRegister& vt2,
2375                      const MemOperand& src) {
2376   USE(vt2);
2377   DCHECK(AreSameFormat(vt, vt2));
2378   DCHECK(AreConsecutive(vt, vt2));
2379   LoadStoreStructSingleAllLanes(vt, src, NEON_LD2R);
2380 }
2381 
ld3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)2382 void Assembler::ld3(const VRegister& vt, const VRegister& vt2,
2383                     const VRegister& vt3, const MemOperand& src) {
2384   USE(vt2);
2385   USE(vt3);
2386   DCHECK(AreSameFormat(vt, vt2, vt3));
2387   DCHECK(AreConsecutive(vt, vt2, vt3));
2388   LoadStoreStruct(vt, src, NEON_LD3);
2389 }
2390 
ld3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,int lane,const MemOperand & src)2391 void Assembler::ld3(const VRegister& vt, const VRegister& vt2,
2392                     const VRegister& vt3, int lane, const MemOperand& src) {
2393   USE(vt2);
2394   USE(vt3);
2395   DCHECK(AreSameFormat(vt, vt2, vt3));
2396   DCHECK(AreConsecutive(vt, vt2, vt3));
2397   LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad3);
2398 }
2399 
ld3r(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)2400 void Assembler::ld3r(const VRegister& vt, const VRegister& vt2,
2401                      const VRegister& vt3, const MemOperand& src) {
2402   USE(vt2);
2403   USE(vt3);
2404   DCHECK(AreSameFormat(vt, vt2, vt3));
2405   DCHECK(AreConsecutive(vt, vt2, vt3));
2406   LoadStoreStructSingleAllLanes(vt, src, NEON_LD3R);
2407 }
2408 
ld4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)2409 void Assembler::ld4(const VRegister& vt, const VRegister& vt2,
2410                     const VRegister& vt3, const VRegister& vt4,
2411                     const MemOperand& src) {
2412   USE(vt2);
2413   USE(vt3);
2414   USE(vt4);
2415   DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2416   DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2417   LoadStoreStruct(vt, src, NEON_LD4);
2418 }
2419 
ld4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,int lane,const MemOperand & src)2420 void Assembler::ld4(const VRegister& vt, const VRegister& vt2,
2421                     const VRegister& vt3, const VRegister& vt4, int lane,
2422                     const MemOperand& src) {
2423   USE(vt2);
2424   USE(vt3);
2425   USE(vt4);
2426   DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2427   DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2428   LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad4);
2429 }
2430 
ld4r(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)2431 void Assembler::ld4r(const VRegister& vt, const VRegister& vt2,
2432                      const VRegister& vt3, const VRegister& vt4,
2433                      const MemOperand& src) {
2434   USE(vt2);
2435   USE(vt3);
2436   USE(vt4);
2437   DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2438   DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2439   LoadStoreStructSingleAllLanes(vt, src, NEON_LD4R);
2440 }
2441 
st1(const VRegister & vt,const MemOperand & src)2442 void Assembler::st1(const VRegister& vt, const MemOperand& src) {
2443   LoadStoreStruct(vt, src, NEON_ST1_1v);
2444 }
2445 
st1(const VRegister & vt,const VRegister & vt2,const MemOperand & src)2446 void Assembler::st1(const VRegister& vt, const VRegister& vt2,
2447                     const MemOperand& src) {
2448   USE(vt2);
2449   DCHECK(AreSameFormat(vt, vt2));
2450   DCHECK(AreConsecutive(vt, vt2));
2451   LoadStoreStruct(vt, src, NEON_ST1_2v);
2452 }
2453 
st1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)2454 void Assembler::st1(const VRegister& vt, const VRegister& vt2,
2455                     const VRegister& vt3, const MemOperand& src) {
2456   USE(vt2);
2457   USE(vt3);
2458   DCHECK(AreSameFormat(vt, vt2, vt3));
2459   DCHECK(AreConsecutive(vt, vt2, vt3));
2460   LoadStoreStruct(vt, src, NEON_ST1_3v);
2461 }
2462 
st1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)2463 void Assembler::st1(const VRegister& vt, const VRegister& vt2,
2464                     const VRegister& vt3, const VRegister& vt4,
2465                     const MemOperand& src) {
2466   USE(vt2);
2467   USE(vt3);
2468   USE(vt4);
2469   DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2470   DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2471   LoadStoreStruct(vt, src, NEON_ST1_4v);
2472 }
2473 
st2(const VRegister & vt,const VRegister & vt2,const MemOperand & dst)2474 void Assembler::st2(const VRegister& vt, const VRegister& vt2,
2475                     const MemOperand& dst) {
2476   USE(vt2);
2477   DCHECK(AreSameFormat(vt, vt2));
2478   DCHECK(AreConsecutive(vt, vt2));
2479   LoadStoreStruct(vt, dst, NEON_ST2);
2480 }
2481 
st2(const VRegister & vt,const VRegister & vt2,int lane,const MemOperand & dst)2482 void Assembler::st2(const VRegister& vt, const VRegister& vt2, int lane,
2483                     const MemOperand& dst) {
2484   USE(vt2);
2485   DCHECK(AreSameFormat(vt, vt2));
2486   DCHECK(AreConsecutive(vt, vt2));
2487   LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore2);
2488 }
2489 
st3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & dst)2490 void Assembler::st3(const VRegister& vt, const VRegister& vt2,
2491                     const VRegister& vt3, const MemOperand& dst) {
2492   USE(vt2);
2493   USE(vt3);
2494   DCHECK(AreSameFormat(vt, vt2, vt3));
2495   DCHECK(AreConsecutive(vt, vt2, vt3));
2496   LoadStoreStruct(vt, dst, NEON_ST3);
2497 }
2498 
st3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,int lane,const MemOperand & dst)2499 void Assembler::st3(const VRegister& vt, const VRegister& vt2,
2500                     const VRegister& vt3, int lane, const MemOperand& dst) {
2501   USE(vt2);
2502   USE(vt3);
2503   DCHECK(AreSameFormat(vt, vt2, vt3));
2504   DCHECK(AreConsecutive(vt, vt2, vt3));
2505   LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore3);
2506 }
2507 
st4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & dst)2508 void Assembler::st4(const VRegister& vt, const VRegister& vt2,
2509                     const VRegister& vt3, const VRegister& vt4,
2510                     const MemOperand& dst) {
2511   USE(vt2);
2512   USE(vt3);
2513   USE(vt4);
2514   DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2515   DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2516   LoadStoreStruct(vt, dst, NEON_ST4);
2517 }
2518 
st4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,int lane,const MemOperand & dst)2519 void Assembler::st4(const VRegister& vt, const VRegister& vt2,
2520                     const VRegister& vt3, const VRegister& vt4, int lane,
2521                     const MemOperand& dst) {
2522   USE(vt2);
2523   USE(vt3);
2524   USE(vt4);
2525   DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2526   DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2527   LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore4);
2528 }
2529 
LoadStoreStructSingle(const VRegister & vt,uint32_t lane,const MemOperand & addr,NEONLoadStoreSingleStructOp op)2530 void Assembler::LoadStoreStructSingle(const VRegister& vt, uint32_t lane,
2531                                       const MemOperand& addr,
2532                                       NEONLoadStoreSingleStructOp op) {
2533   LoadStoreStructVerify(vt, addr, op);
2534 
2535   // We support vt arguments of the form vt.VxT() or vt.T(), where x is the
2536   // number of lanes, and T is b, h, s or d.
2537   unsigned lane_size = vt.LaneSizeInBytes();
2538   DCHECK_LT(lane, kQRegSize / lane_size);
2539 
2540   // Lane size is encoded in the opcode field. Lane index is encoded in the Q,
2541   // S and size fields.
2542   lane *= lane_size;
2543 
2544   // Encodings for S[0]/D[0] and S[2]/D[1] are distinguished using the least-
2545   // significant bit of the size field, so we increment lane here to account for
2546   // that.
2547   if (lane_size == 8) lane++;
2548 
2549   Instr size = (lane << NEONLSSize_offset) & NEONLSSize_mask;
2550   Instr s = (lane << (NEONS_offset - 2)) & NEONS_mask;
2551   Instr q = (lane << (NEONQ_offset - 3)) & NEONQ_mask;
2552 
2553   Instr instr = op;
2554   switch (lane_size) {
2555     case 1:
2556       instr |= NEONLoadStoreSingle_b;
2557       break;
2558     case 2:
2559       instr |= NEONLoadStoreSingle_h;
2560       break;
2561     case 4:
2562       instr |= NEONLoadStoreSingle_s;
2563       break;
2564     default:
2565       DCHECK_EQ(lane_size, 8U);
2566       instr |= NEONLoadStoreSingle_d;
2567   }
2568 
2569   Emit(instr | LoadStoreStructAddrModeField(addr) | q | size | s | Rt(vt));
2570 }
2571 
ld1(const VRegister & vt,int lane,const MemOperand & src)2572 void Assembler::ld1(const VRegister& vt, int lane, const MemOperand& src) {
2573   LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad1);
2574 }
2575 
ld1r(const VRegister & vt,const MemOperand & src)2576 void Assembler::ld1r(const VRegister& vt, const MemOperand& src) {
2577   LoadStoreStructSingleAllLanes(vt, src, NEON_LD1R);
2578 }
2579 
st1(const VRegister & vt,int lane,const MemOperand & dst)2580 void Assembler::st1(const VRegister& vt, int lane, const MemOperand& dst) {
2581   LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore1);
2582 }
2583 
dmb(BarrierDomain domain,BarrierType type)2584 void Assembler::dmb(BarrierDomain domain, BarrierType type) {
2585   Emit(DMB | ImmBarrierDomain(domain) | ImmBarrierType(type));
2586 }
2587 
dsb(BarrierDomain domain,BarrierType type)2588 void Assembler::dsb(BarrierDomain domain, BarrierType type) {
2589   Emit(DSB | ImmBarrierDomain(domain) | ImmBarrierType(type));
2590 }
2591 
isb()2592 void Assembler::isb() {
2593   Emit(ISB | ImmBarrierDomain(FullSystem) | ImmBarrierType(BarrierAll));
2594 }
2595 
csdb()2596 void Assembler::csdb() { hint(CSDB); }
2597 
fmov(const VRegister & vd,double imm)2598 void Assembler::fmov(const VRegister& vd, double imm) {
2599   if (vd.IsScalar()) {
2600     DCHECK(vd.Is1D());
2601     Emit(FMOV_d_imm | Rd(vd) | ImmFP(imm));
2602   } else {
2603     DCHECK(vd.Is2D());
2604     Instr op = NEONModifiedImmediate_MOVI | NEONModifiedImmediateOpBit;
2605     Emit(NEON_Q | op | ImmNEONFP(imm) | NEONCmode(0xF) | Rd(vd));
2606   }
2607 }
2608 
fmov(const VRegister & vd,float imm)2609 void Assembler::fmov(const VRegister& vd, float imm) {
2610   if (vd.IsScalar()) {
2611     DCHECK(vd.Is1S());
2612     Emit(FMOV_s_imm | Rd(vd) | ImmFP(imm));
2613   } else {
2614     DCHECK(vd.Is2S() | vd.Is4S());
2615     Instr op = NEONModifiedImmediate_MOVI;
2616     Instr q = vd.Is4S() ? NEON_Q : 0;
2617     Emit(q | op | ImmNEONFP(imm) | NEONCmode(0xF) | Rd(vd));
2618   }
2619 }
2620 
fmov(const Register & rd,const VRegister & fn)2621 void Assembler::fmov(const Register& rd, const VRegister& fn) {
2622   DCHECK_EQ(rd.SizeInBits(), fn.SizeInBits());
2623   FPIntegerConvertOp op = rd.Is32Bits() ? FMOV_ws : FMOV_xd;
2624   Emit(op | Rd(rd) | Rn(fn));
2625 }
2626 
fmov(const VRegister & vd,const Register & rn)2627 void Assembler::fmov(const VRegister& vd, const Register& rn) {
2628   DCHECK_EQ(vd.SizeInBits(), rn.SizeInBits());
2629   FPIntegerConvertOp op = vd.Is32Bits() ? FMOV_sw : FMOV_dx;
2630   Emit(op | Rd(vd) | Rn(rn));
2631 }
2632 
fmov(const VRegister & vd,const VRegister & vn)2633 void Assembler::fmov(const VRegister& vd, const VRegister& vn) {
2634   DCHECK_EQ(vd.SizeInBits(), vn.SizeInBits());
2635   Emit(FPType(vd) | FMOV | Rd(vd) | Rn(vn));
2636 }
2637 
fmov(const VRegister & vd,int index,const Register & rn)2638 void Assembler::fmov(const VRegister& vd, int index, const Register& rn) {
2639   DCHECK((index == 1) && vd.Is1D() && rn.IsX());
2640   USE(index);
2641   Emit(FMOV_d1_x | Rd(vd) | Rn(rn));
2642 }
2643 
fmov(const Register & rd,const VRegister & vn,int index)2644 void Assembler::fmov(const Register& rd, const VRegister& vn, int index) {
2645   DCHECK((index == 1) && vn.Is1D() && rd.IsX());
2646   USE(index);
2647   Emit(FMOV_x_d1 | Rd(rd) | Rn(vn));
2648 }
2649 
fmadd(const VRegister & fd,const VRegister & fn,const VRegister & fm,const VRegister & fa)2650 void Assembler::fmadd(const VRegister& fd, const VRegister& fn,
2651                       const VRegister& fm, const VRegister& fa) {
2652   FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMADD_s : FMADD_d);
2653 }
2654 
fmsub(const VRegister & fd,const VRegister & fn,const VRegister & fm,const VRegister & fa)2655 void Assembler::fmsub(const VRegister& fd, const VRegister& fn,
2656                       const VRegister& fm, const VRegister& fa) {
2657   FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMSUB_s : FMSUB_d);
2658 }
2659 
fnmadd(const VRegister & fd,const VRegister & fn,const VRegister & fm,const VRegister & fa)2660 void Assembler::fnmadd(const VRegister& fd, const VRegister& fn,
2661                        const VRegister& fm, const VRegister& fa) {
2662   FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMADD_s : FNMADD_d);
2663 }
2664 
fnmsub(const VRegister & fd,const VRegister & fn,const VRegister & fm,const VRegister & fa)2665 void Assembler::fnmsub(const VRegister& fd, const VRegister& fn,
2666                        const VRegister& fm, const VRegister& fa) {
2667   FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMSUB_s : FNMSUB_d);
2668 }
2669 
fnmul(const VRegister & vd,const VRegister & vn,const VRegister & vm)2670 void Assembler::fnmul(const VRegister& vd, const VRegister& vn,
2671                       const VRegister& vm) {
2672   DCHECK(AreSameSizeAndType(vd, vn, vm));
2673   Instr op = vd.Is1S() ? FNMUL_s : FNMUL_d;
2674   Emit(FPType(vd) | op | Rm(vm) | Rn(vn) | Rd(vd));
2675 }
2676 
fcmp(const VRegister & fn,const VRegister & fm)2677 void Assembler::fcmp(const VRegister& fn, const VRegister& fm) {
2678   DCHECK_EQ(fn.SizeInBits(), fm.SizeInBits());
2679   Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn));
2680 }
2681 
fcmp(const VRegister & fn,double value)2682 void Assembler::fcmp(const VRegister& fn, double value) {
2683   USE(value);
2684   // Although the fcmp instruction can strictly only take an immediate value of
2685   // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't
2686   // affect the result of the comparison.
2687   DCHECK_EQ(value, 0.0);
2688   Emit(FPType(fn) | FCMP_zero | Rn(fn));
2689 }
2690 
fccmp(const VRegister & fn,const VRegister & fm,StatusFlags nzcv,Condition cond)2691 void Assembler::fccmp(const VRegister& fn, const VRegister& fm,
2692                       StatusFlags nzcv, Condition cond) {
2693   DCHECK_EQ(fn.SizeInBits(), fm.SizeInBits());
2694   Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv));
2695 }
2696 
fcsel(const VRegister & fd,const VRegister & fn,const VRegister & fm,Condition cond)2697 void Assembler::fcsel(const VRegister& fd, const VRegister& fn,
2698                       const VRegister& fm, Condition cond) {
2699   DCHECK_EQ(fd.SizeInBits(), fn.SizeInBits());
2700   DCHECK_EQ(fd.SizeInBits(), fm.SizeInBits());
2701   Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd));
2702 }
2703 
NEONFPConvertToInt(const Register & rd,const VRegister & vn,Instr op)2704 void Assembler::NEONFPConvertToInt(const Register& rd, const VRegister& vn,
2705                                    Instr op) {
2706   Emit(SF(rd) | FPType(vn) | op | Rn(vn) | Rd(rd));
2707 }
2708 
NEONFPConvertToInt(const VRegister & vd,const VRegister & vn,Instr op)2709 void Assembler::NEONFPConvertToInt(const VRegister& vd, const VRegister& vn,
2710                                    Instr op) {
2711   if (vn.IsScalar()) {
2712     DCHECK((vd.Is1S() && vn.Is1S()) || (vd.Is1D() && vn.Is1D()));
2713     op |= NEON_Q | NEONScalar;
2714   }
2715   Emit(FPFormat(vn) | op | Rn(vn) | Rd(vd));
2716 }
2717 
fcvt(const VRegister & vd,const VRegister & vn)2718 void Assembler::fcvt(const VRegister& vd, const VRegister& vn) {
2719   FPDataProcessing1SourceOp op;
2720   if (vd.Is1D()) {
2721     DCHECK(vn.Is1S() || vn.Is1H());
2722     op = vn.Is1S() ? FCVT_ds : FCVT_dh;
2723   } else if (vd.Is1S()) {
2724     DCHECK(vn.Is1D() || vn.Is1H());
2725     op = vn.Is1D() ? FCVT_sd : FCVT_sh;
2726   } else {
2727     DCHECK(vd.Is1H());
2728     DCHECK(vn.Is1D() || vn.Is1S());
2729     op = vn.Is1D() ? FCVT_hd : FCVT_hs;
2730   }
2731   FPDataProcessing1Source(vd, vn, op);
2732 }
2733 
fcvtl(const VRegister & vd,const VRegister & vn)2734 void Assembler::fcvtl(const VRegister& vd, const VRegister& vn) {
2735   DCHECK((vd.Is4S() && vn.Is4H()) || (vd.Is2D() && vn.Is2S()));
2736   Instr format = vd.Is2D() ? (1 << NEONSize_offset) : 0;
2737   Emit(format | NEON_FCVTL | Rn(vn) | Rd(vd));
2738 }
2739 
fcvtl2(const VRegister & vd,const VRegister & vn)2740 void Assembler::fcvtl2(const VRegister& vd, const VRegister& vn) {
2741   DCHECK((vd.Is4S() && vn.Is8H()) || (vd.Is2D() && vn.Is4S()));
2742   Instr format = vd.Is2D() ? (1 << NEONSize_offset) : 0;
2743   Emit(NEON_Q | format | NEON_FCVTL | Rn(vn) | Rd(vd));
2744 }
2745 
fcvtn(const VRegister & vd,const VRegister & vn)2746 void Assembler::fcvtn(const VRegister& vd, const VRegister& vn) {
2747   DCHECK((vn.Is4S() && vd.Is4H()) || (vn.Is2D() && vd.Is2S()));
2748   Instr format = vn.Is2D() ? (1 << NEONSize_offset) : 0;
2749   Emit(format | NEON_FCVTN | Rn(vn) | Rd(vd));
2750 }
2751 
fcvtn2(const VRegister & vd,const VRegister & vn)2752 void Assembler::fcvtn2(const VRegister& vd, const VRegister& vn) {
2753   DCHECK((vn.Is4S() && vd.Is8H()) || (vn.Is2D() && vd.Is4S()));
2754   Instr format = vn.Is2D() ? (1 << NEONSize_offset) : 0;
2755   Emit(NEON_Q | format | NEON_FCVTN | Rn(vn) | Rd(vd));
2756 }
2757 
fcvtxn(const VRegister & vd,const VRegister & vn)2758 void Assembler::fcvtxn(const VRegister& vd, const VRegister& vn) {
2759   Instr format = 1 << NEONSize_offset;
2760   if (vd.IsScalar()) {
2761     DCHECK(vd.Is1S() && vn.Is1D());
2762     Emit(format | NEON_FCVTXN_scalar | Rn(vn) | Rd(vd));
2763   } else {
2764     DCHECK(vd.Is2S() && vn.Is2D());
2765     Emit(format | NEON_FCVTXN | Rn(vn) | Rd(vd));
2766   }
2767 }
2768 
fcvtxn2(const VRegister & vd,const VRegister & vn)2769 void Assembler::fcvtxn2(const VRegister& vd, const VRegister& vn) {
2770   DCHECK(vd.Is4S() && vn.Is2D());
2771   Instr format = 1 << NEONSize_offset;
2772   Emit(NEON_Q | format | NEON_FCVTXN | Rn(vn) | Rd(vd));
2773 }
2774 
fjcvtzs(const Register & rd,const VRegister & vn)2775 void Assembler::fjcvtzs(const Register& rd, const VRegister& vn) {
2776   DCHECK(rd.IsW() && vn.Is1D());
2777   Emit(FJCVTZS | Rn(vn) | Rd(rd));
2778 }
2779 
2780 #define NEON_FP2REGMISC_FCVT_LIST(V) \
2781   V(fcvtnu, NEON_FCVTNU, FCVTNU)     \
2782   V(fcvtns, NEON_FCVTNS, FCVTNS)     \
2783   V(fcvtpu, NEON_FCVTPU, FCVTPU)     \
2784   V(fcvtps, NEON_FCVTPS, FCVTPS)     \
2785   V(fcvtmu, NEON_FCVTMU, FCVTMU)     \
2786   V(fcvtms, NEON_FCVTMS, FCVTMS)     \
2787   V(fcvtau, NEON_FCVTAU, FCVTAU)     \
2788   V(fcvtas, NEON_FCVTAS, FCVTAS)
2789 
2790 #define DEFINE_ASM_FUNCS(FN, VEC_OP, SCA_OP)                     \
2791   void Assembler::FN(const Register& rd, const VRegister& vn) {  \
2792     NEONFPConvertToInt(rd, vn, SCA_OP);                          \
2793   }                                                              \
2794   void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
2795     NEONFPConvertToInt(vd, vn, VEC_OP);                          \
2796   }
NEON_FP2REGMISC_FCVT_LIST(DEFINE_ASM_FUNCS)2797 NEON_FP2REGMISC_FCVT_LIST(DEFINE_ASM_FUNCS)
2798 #undef DEFINE_ASM_FUNCS
2799 
2800 void Assembler::scvtf(const VRegister& vd, const VRegister& vn, int fbits) {
2801   DCHECK_GE(fbits, 0);
2802   if (fbits == 0) {
2803     NEONFP2RegMisc(vd, vn, NEON_SCVTF);
2804   } else {
2805     DCHECK(vd.Is1D() || vd.Is1S() || vd.Is2D() || vd.Is2S() || vd.Is4S());
2806     NEONShiftRightImmediate(vd, vn, fbits, NEON_SCVTF_imm);
2807   }
2808 }
2809 
ucvtf(const VRegister & vd,const VRegister & vn,int fbits)2810 void Assembler::ucvtf(const VRegister& vd, const VRegister& vn, int fbits) {
2811   DCHECK_GE(fbits, 0);
2812   if (fbits == 0) {
2813     NEONFP2RegMisc(vd, vn, NEON_UCVTF);
2814   } else {
2815     DCHECK(vd.Is1D() || vd.Is1S() || vd.Is2D() || vd.Is2S() || vd.Is4S());
2816     NEONShiftRightImmediate(vd, vn, fbits, NEON_UCVTF_imm);
2817   }
2818 }
2819 
scvtf(const VRegister & vd,const Register & rn,int fbits)2820 void Assembler::scvtf(const VRegister& vd, const Register& rn, int fbits) {
2821   DCHECK_GE(fbits, 0);
2822   if (fbits == 0) {
2823     Emit(SF(rn) | FPType(vd) | SCVTF | Rn(rn) | Rd(vd));
2824   } else {
2825     Emit(SF(rn) | FPType(vd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
2826          Rd(vd));
2827   }
2828 }
2829 
ucvtf(const VRegister & fd,const Register & rn,int fbits)2830 void Assembler::ucvtf(const VRegister& fd, const Register& rn, int fbits) {
2831   DCHECK_GE(fbits, 0);
2832   if (fbits == 0) {
2833     Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd));
2834   } else {
2835     Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
2836          Rd(fd));
2837   }
2838 }
2839 
NEON3Same(const VRegister & vd,const VRegister & vn,const VRegister & vm,NEON3SameOp vop)2840 void Assembler::NEON3Same(const VRegister& vd, const VRegister& vn,
2841                           const VRegister& vm, NEON3SameOp vop) {
2842   DCHECK(AreSameFormat(vd, vn, vm));
2843   DCHECK(vd.IsVector() || !vd.IsQ());
2844 
2845   Instr format, op = vop;
2846   if (vd.IsScalar()) {
2847     op |= NEON_Q | NEONScalar;
2848     format = SFormat(vd);
2849   } else {
2850     format = VFormat(vd);
2851   }
2852 
2853   Emit(format | op | Rm(vm) | Rn(vn) | Rd(vd));
2854 }
2855 
NEONFP3Same(const VRegister & vd,const VRegister & vn,const VRegister & vm,Instr op)2856 void Assembler::NEONFP3Same(const VRegister& vd, const VRegister& vn,
2857                             const VRegister& vm, Instr op) {
2858   DCHECK(AreSameFormat(vd, vn, vm));
2859   Emit(FPFormat(vd) | op | Rm(vm) | Rn(vn) | Rd(vd));
2860 }
2861 
2862 #define NEON_FP2REGMISC_LIST(V)                 \
2863   V(fabs, NEON_FABS, FABS)                      \
2864   V(fneg, NEON_FNEG, FNEG)                      \
2865   V(fsqrt, NEON_FSQRT, FSQRT)                   \
2866   V(frintn, NEON_FRINTN, FRINTN)                \
2867   V(frinta, NEON_FRINTA, FRINTA)                \
2868   V(frintp, NEON_FRINTP, FRINTP)                \
2869   V(frintm, NEON_FRINTM, FRINTM)                \
2870   V(frintx, NEON_FRINTX, FRINTX)                \
2871   V(frintz, NEON_FRINTZ, FRINTZ)                \
2872   V(frinti, NEON_FRINTI, FRINTI)                \
2873   V(frsqrte, NEON_FRSQRTE, NEON_FRSQRTE_scalar) \
2874   V(frecpe, NEON_FRECPE, NEON_FRECPE_scalar)
2875 
2876 #define DEFINE_ASM_FUNC(FN, VEC_OP, SCA_OP)                      \
2877   void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
2878     Instr op;                                                    \
2879     if (vd.IsScalar()) {                                         \
2880       DCHECK(vd.Is1S() || vd.Is1D());                            \
2881       op = SCA_OP;                                               \
2882     } else {                                                     \
2883       DCHECK(vd.Is2S() || vd.Is2D() || vd.Is4S());               \
2884       op = VEC_OP;                                               \
2885     }                                                            \
2886     NEONFP2RegMisc(vd, vn, op);                                  \
2887   }
NEON_FP2REGMISC_LIST(DEFINE_ASM_FUNC)2888 NEON_FP2REGMISC_LIST(DEFINE_ASM_FUNC)
2889 #undef DEFINE_ASM_FUNC
2890 
2891 void Assembler::shll(const VRegister& vd, const VRegister& vn, int shift) {
2892   DCHECK((vd.Is8H() && vn.Is8B() && shift == 8) ||
2893          (vd.Is4S() && vn.Is4H() && shift == 16) ||
2894          (vd.Is2D() && vn.Is2S() && shift == 32));
2895   USE(shift);
2896   Emit(VFormat(vn) | NEON_SHLL | Rn(vn) | Rd(vd));
2897 }
2898 
shll2(const VRegister & vd,const VRegister & vn,int shift)2899 void Assembler::shll2(const VRegister& vd, const VRegister& vn, int shift) {
2900   USE(shift);
2901   DCHECK((vd.Is8H() && vn.Is16B() && shift == 8) ||
2902          (vd.Is4S() && vn.Is8H() && shift == 16) ||
2903          (vd.Is2D() && vn.Is4S() && shift == 32));
2904   Emit(VFormat(vn) | NEON_SHLL | Rn(vn) | Rd(vd));
2905 }
2906 
NEONFP2RegMisc(const VRegister & vd,const VRegister & vn,NEON2RegMiscOp vop,double value)2907 void Assembler::NEONFP2RegMisc(const VRegister& vd, const VRegister& vn,
2908                                NEON2RegMiscOp vop, double value) {
2909   DCHECK(AreSameFormat(vd, vn));
2910   DCHECK_EQ(value, 0.0);
2911   USE(value);
2912 
2913   Instr op = vop;
2914   if (vd.IsScalar()) {
2915     DCHECK(vd.Is1S() || vd.Is1D());
2916     op |= NEON_Q | NEONScalar;
2917   } else {
2918     DCHECK(vd.Is2S() || vd.Is2D() || vd.Is4S());
2919   }
2920 
2921   Emit(FPFormat(vd) | op | Rn(vn) | Rd(vd));
2922 }
2923 
fcmeq(const VRegister & vd,const VRegister & vn,double value)2924 void Assembler::fcmeq(const VRegister& vd, const VRegister& vn, double value) {
2925   NEONFP2RegMisc(vd, vn, NEON_FCMEQ_zero, value);
2926 }
2927 
fcmge(const VRegister & vd,const VRegister & vn,double value)2928 void Assembler::fcmge(const VRegister& vd, const VRegister& vn, double value) {
2929   NEONFP2RegMisc(vd, vn, NEON_FCMGE_zero, value);
2930 }
2931 
fcmgt(const VRegister & vd,const VRegister & vn,double value)2932 void Assembler::fcmgt(const VRegister& vd, const VRegister& vn, double value) {
2933   NEONFP2RegMisc(vd, vn, NEON_FCMGT_zero, value);
2934 }
2935 
fcmle(const VRegister & vd,const VRegister & vn,double value)2936 void Assembler::fcmle(const VRegister& vd, const VRegister& vn, double value) {
2937   NEONFP2RegMisc(vd, vn, NEON_FCMLE_zero, value);
2938 }
2939 
fcmlt(const VRegister & vd,const VRegister & vn,double value)2940 void Assembler::fcmlt(const VRegister& vd, const VRegister& vn, double value) {
2941   NEONFP2RegMisc(vd, vn, NEON_FCMLT_zero, value);
2942 }
2943 
frecpx(const VRegister & vd,const VRegister & vn)2944 void Assembler::frecpx(const VRegister& vd, const VRegister& vn) {
2945   DCHECK(vd.IsScalar());
2946   DCHECK(AreSameFormat(vd, vn));
2947   DCHECK(vd.Is1S() || vd.Is1D());
2948   Emit(FPFormat(vd) | NEON_FRECPX_scalar | Rn(vn) | Rd(vd));
2949 }
2950 
fcvtzs(const Register & rd,const VRegister & vn,int fbits)2951 void Assembler::fcvtzs(const Register& rd, const VRegister& vn, int fbits) {
2952   DCHECK(vn.Is1S() || vn.Is1D());
2953   DCHECK((fbits >= 0) && (fbits <= rd.SizeInBits()));
2954   if (fbits == 0) {
2955     Emit(SF(rd) | FPType(vn) | FCVTZS | Rn(vn) | Rd(rd));
2956   } else {
2957     Emit(SF(rd) | FPType(vn) | FCVTZS_fixed | FPScale(64 - fbits) | Rn(vn) |
2958          Rd(rd));
2959   }
2960 }
2961 
fcvtzs(const VRegister & vd,const VRegister & vn,int fbits)2962 void Assembler::fcvtzs(const VRegister& vd, const VRegister& vn, int fbits) {
2963   DCHECK_GE(fbits, 0);
2964   if (fbits == 0) {
2965     NEONFP2RegMisc(vd, vn, NEON_FCVTZS);
2966   } else {
2967     DCHECK(vd.Is1D() || vd.Is1S() || vd.Is2D() || vd.Is2S() || vd.Is4S());
2968     NEONShiftRightImmediate(vd, vn, fbits, NEON_FCVTZS_imm);
2969   }
2970 }
2971 
fcvtzu(const Register & rd,const VRegister & vn,int fbits)2972 void Assembler::fcvtzu(const Register& rd, const VRegister& vn, int fbits) {
2973   DCHECK(vn.Is1S() || vn.Is1D());
2974   DCHECK((fbits >= 0) && (fbits <= rd.SizeInBits()));
2975   if (fbits == 0) {
2976     Emit(SF(rd) | FPType(vn) | FCVTZU | Rn(vn) | Rd(rd));
2977   } else {
2978     Emit(SF(rd) | FPType(vn) | FCVTZU_fixed | FPScale(64 - fbits) | Rn(vn) |
2979          Rd(rd));
2980   }
2981 }
2982 
fcvtzu(const VRegister & vd,const VRegister & vn,int fbits)2983 void Assembler::fcvtzu(const VRegister& vd, const VRegister& vn, int fbits) {
2984   DCHECK_GE(fbits, 0);
2985   if (fbits == 0) {
2986     NEONFP2RegMisc(vd, vn, NEON_FCVTZU);
2987   } else {
2988     DCHECK(vd.Is1D() || vd.Is1S() || vd.Is2D() || vd.Is2S() || vd.Is4S());
2989     NEONShiftRightImmediate(vd, vn, fbits, NEON_FCVTZU_imm);
2990   }
2991 }
2992 
NEONFP2RegMisc(const VRegister & vd,const VRegister & vn,Instr op)2993 void Assembler::NEONFP2RegMisc(const VRegister& vd, const VRegister& vn,
2994                                Instr op) {
2995   DCHECK(AreSameFormat(vd, vn));
2996   Emit(FPFormat(vd) | op | Rn(vn) | Rd(vd));
2997 }
2998 
NEON2RegMisc(const VRegister & vd,const VRegister & vn,NEON2RegMiscOp vop,int value)2999 void Assembler::NEON2RegMisc(const VRegister& vd, const VRegister& vn,
3000                              NEON2RegMiscOp vop, int value) {
3001   DCHECK(AreSameFormat(vd, vn));
3002   DCHECK_EQ(value, 0);
3003   USE(value);
3004 
3005   Instr format, op = vop;
3006   if (vd.IsScalar()) {
3007     op |= NEON_Q | NEONScalar;
3008     format = SFormat(vd);
3009   } else {
3010     format = VFormat(vd);
3011   }
3012 
3013   Emit(format | op | Rn(vn) | Rd(vd));
3014 }
3015 
cmeq(const VRegister & vd,const VRegister & vn,int value)3016 void Assembler::cmeq(const VRegister& vd, const VRegister& vn, int value) {
3017   DCHECK(vd.IsVector() || vd.Is1D());
3018   NEON2RegMisc(vd, vn, NEON_CMEQ_zero, value);
3019 }
3020 
cmge(const VRegister & vd,const VRegister & vn,int value)3021 void Assembler::cmge(const VRegister& vd, const VRegister& vn, int value) {
3022   DCHECK(vd.IsVector() || vd.Is1D());
3023   NEON2RegMisc(vd, vn, NEON_CMGE_zero, value);
3024 }
3025 
cmgt(const VRegister & vd,const VRegister & vn,int value)3026 void Assembler::cmgt(const VRegister& vd, const VRegister& vn, int value) {
3027   DCHECK(vd.IsVector() || vd.Is1D());
3028   NEON2RegMisc(vd, vn, NEON_CMGT_zero, value);
3029 }
3030 
cmle(const VRegister & vd,const VRegister & vn,int value)3031 void Assembler::cmle(const VRegister& vd, const VRegister& vn, int value) {
3032   DCHECK(vd.IsVector() || vd.Is1D());
3033   NEON2RegMisc(vd, vn, NEON_CMLE_zero, value);
3034 }
3035 
cmlt(const VRegister & vd,const VRegister & vn,int value)3036 void Assembler::cmlt(const VRegister& vd, const VRegister& vn, int value) {
3037   DCHECK(vd.IsVector() || vd.Is1D());
3038   NEON2RegMisc(vd, vn, NEON_CMLT_zero, value);
3039 }
3040 
3041 #define NEON_3SAME_LIST(V)                                         \
3042   V(add, NEON_ADD, vd.IsVector() || vd.Is1D())                     \
3043   V(addp, NEON_ADDP, vd.IsVector() || vd.Is1D())                   \
3044   V(sub, NEON_SUB, vd.IsVector() || vd.Is1D())                     \
3045   V(cmeq, NEON_CMEQ, vd.IsVector() || vd.Is1D())                   \
3046   V(cmge, NEON_CMGE, vd.IsVector() || vd.Is1D())                   \
3047   V(cmgt, NEON_CMGT, vd.IsVector() || vd.Is1D())                   \
3048   V(cmhi, NEON_CMHI, vd.IsVector() || vd.Is1D())                   \
3049   V(cmhs, NEON_CMHS, vd.IsVector() || vd.Is1D())                   \
3050   V(cmtst, NEON_CMTST, vd.IsVector() || vd.Is1D())                 \
3051   V(sshl, NEON_SSHL, vd.IsVector() || vd.Is1D())                   \
3052   V(ushl, NEON_USHL, vd.IsVector() || vd.Is1D())                   \
3053   V(srshl, NEON_SRSHL, vd.IsVector() || vd.Is1D())                 \
3054   V(urshl, NEON_URSHL, vd.IsVector() || vd.Is1D())                 \
3055   V(sqdmulh, NEON_SQDMULH, vd.IsLaneSizeH() || vd.IsLaneSizeS())   \
3056   V(sqrdmulh, NEON_SQRDMULH, vd.IsLaneSizeH() || vd.IsLaneSizeS()) \
3057   V(shadd, NEON_SHADD, vd.IsVector() && !vd.IsLaneSizeD())         \
3058   V(uhadd, NEON_UHADD, vd.IsVector() && !vd.IsLaneSizeD())         \
3059   V(srhadd, NEON_SRHADD, vd.IsVector() && !vd.IsLaneSizeD())       \
3060   V(urhadd, NEON_URHADD, vd.IsVector() && !vd.IsLaneSizeD())       \
3061   V(shsub, NEON_SHSUB, vd.IsVector() && !vd.IsLaneSizeD())         \
3062   V(uhsub, NEON_UHSUB, vd.IsVector() && !vd.IsLaneSizeD())         \
3063   V(smax, NEON_SMAX, vd.IsVector() && !vd.IsLaneSizeD())           \
3064   V(smaxp, NEON_SMAXP, vd.IsVector() && !vd.IsLaneSizeD())         \
3065   V(smin, NEON_SMIN, vd.IsVector() && !vd.IsLaneSizeD())           \
3066   V(sminp, NEON_SMINP, vd.IsVector() && !vd.IsLaneSizeD())         \
3067   V(umax, NEON_UMAX, vd.IsVector() && !vd.IsLaneSizeD())           \
3068   V(umaxp, NEON_UMAXP, vd.IsVector() && !vd.IsLaneSizeD())         \
3069   V(umin, NEON_UMIN, vd.IsVector() && !vd.IsLaneSizeD())           \
3070   V(uminp, NEON_UMINP, vd.IsVector() && !vd.IsLaneSizeD())         \
3071   V(saba, NEON_SABA, vd.IsVector() && !vd.IsLaneSizeD())           \
3072   V(sabd, NEON_SABD, vd.IsVector() && !vd.IsLaneSizeD())           \
3073   V(uaba, NEON_UABA, vd.IsVector() && !vd.IsLaneSizeD())           \
3074   V(uabd, NEON_UABD, vd.IsVector() && !vd.IsLaneSizeD())           \
3075   V(mla, NEON_MLA, vd.IsVector() && !vd.IsLaneSizeD())             \
3076   V(mls, NEON_MLS, vd.IsVector() && !vd.IsLaneSizeD())             \
3077   V(mul, NEON_MUL, vd.IsVector() && !vd.IsLaneSizeD())             \
3078   V(and_, NEON_AND, vd.Is8B() || vd.Is16B())                       \
3079   V(orr, NEON_ORR, vd.Is8B() || vd.Is16B())                        \
3080   V(orn, NEON_ORN, vd.Is8B() || vd.Is16B())                        \
3081   V(eor, NEON_EOR, vd.Is8B() || vd.Is16B())                        \
3082   V(bic, NEON_BIC, vd.Is8B() || vd.Is16B())                        \
3083   V(bit, NEON_BIT, vd.Is8B() || vd.Is16B())                        \
3084   V(bif, NEON_BIF, vd.Is8B() || vd.Is16B())                        \
3085   V(bsl, NEON_BSL, vd.Is8B() || vd.Is16B())                        \
3086   V(pmul, NEON_PMUL, vd.Is8B() || vd.Is16B())                      \
3087   V(uqadd, NEON_UQADD, true)                                       \
3088   V(sqadd, NEON_SQADD, true)                                       \
3089   V(uqsub, NEON_UQSUB, true)                                       \
3090   V(sqsub, NEON_SQSUB, true)                                       \
3091   V(sqshl, NEON_SQSHL, true)                                       \
3092   V(uqshl, NEON_UQSHL, true)                                       \
3093   V(sqrshl, NEON_SQRSHL, true)                                     \
3094   V(uqrshl, NEON_UQRSHL, true)
3095 
3096 #define DEFINE_ASM_FUNC(FN, OP, AS)                            \
3097   void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3098                      const VRegister& vm) {                    \
3099     DCHECK(AS);                                                \
3100     NEON3Same(vd, vn, vm, OP);                                 \
3101   }
3102 NEON_3SAME_LIST(DEFINE_ASM_FUNC)
3103 #undef DEFINE_ASM_FUNC
3104 
3105 #define NEON_FP3SAME_LIST_V2(V)                 \
3106   V(fadd, NEON_FADD, FADD)                      \
3107   V(fsub, NEON_FSUB, FSUB)                      \
3108   V(fmul, NEON_FMUL, FMUL)                      \
3109   V(fdiv, NEON_FDIV, FDIV)                      \
3110   V(fmax, NEON_FMAX, FMAX)                      \
3111   V(fmaxnm, NEON_FMAXNM, FMAXNM)                \
3112   V(fmin, NEON_FMIN, FMIN)                      \
3113   V(fminnm, NEON_FMINNM, FMINNM)                \
3114   V(fmulx, NEON_FMULX, NEON_FMULX_scalar)       \
3115   V(frecps, NEON_FRECPS, NEON_FRECPS_scalar)    \
3116   V(frsqrts, NEON_FRSQRTS, NEON_FRSQRTS_scalar) \
3117   V(fabd, NEON_FABD, NEON_FABD_scalar)          \
3118   V(fmla, NEON_FMLA, 0)                         \
3119   V(fmls, NEON_FMLS, 0)                         \
3120   V(facge, NEON_FACGE, NEON_FACGE_scalar)       \
3121   V(facgt, NEON_FACGT, NEON_FACGT_scalar)       \
3122   V(fcmeq, NEON_FCMEQ, NEON_FCMEQ_scalar)       \
3123   V(fcmge, NEON_FCMGE, NEON_FCMGE_scalar)       \
3124   V(fcmgt, NEON_FCMGT, NEON_FCMGT_scalar)       \
3125   V(faddp, NEON_FADDP, 0)                       \
3126   V(fmaxp, NEON_FMAXP, 0)                       \
3127   V(fminp, NEON_FMINP, 0)                       \
3128   V(fmaxnmp, NEON_FMAXNMP, 0)                   \
3129   V(fminnmp, NEON_FMINNMP, 0)
3130 
3131 #define DEFINE_ASM_FUNC(FN, VEC_OP, SCA_OP)                    \
3132   void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3133                      const VRegister& vm) {                    \
3134     Instr op;                                                  \
3135     if ((SCA_OP != 0) && vd.IsScalar()) {                      \
3136       DCHECK(vd.Is1S() || vd.Is1D());                          \
3137       op = SCA_OP;                                             \
3138     } else {                                                   \
3139       DCHECK(vd.IsVector());                                   \
3140       DCHECK(vd.Is2S() || vd.Is2D() || vd.Is4S());             \
3141       op = VEC_OP;                                             \
3142     }                                                          \
3143     NEONFP3Same(vd, vn, vm, op);                               \
3144   }
NEON_FP3SAME_LIST_V2(DEFINE_ASM_FUNC)3145 NEON_FP3SAME_LIST_V2(DEFINE_ASM_FUNC)
3146 #undef DEFINE_ASM_FUNC
3147 
3148 void Assembler::addp(const VRegister& vd, const VRegister& vn) {
3149   DCHECK((vd.Is1D() && vn.Is2D()));
3150   Emit(SFormat(vd) | NEON_ADDP_scalar | Rn(vn) | Rd(vd));
3151 }
3152 
faddp(const VRegister & vd,const VRegister & vn)3153 void Assembler::faddp(const VRegister& vd, const VRegister& vn) {
3154   DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3155   Emit(FPFormat(vd) | NEON_FADDP_scalar | Rn(vn) | Rd(vd));
3156 }
3157 
fmaxp(const VRegister & vd,const VRegister & vn)3158 void Assembler::fmaxp(const VRegister& vd, const VRegister& vn) {
3159   DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3160   Emit(FPFormat(vd) | NEON_FMAXP_scalar | Rn(vn) | Rd(vd));
3161 }
3162 
fminp(const VRegister & vd,const VRegister & vn)3163 void Assembler::fminp(const VRegister& vd, const VRegister& vn) {
3164   DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3165   Emit(FPFormat(vd) | NEON_FMINP_scalar | Rn(vn) | Rd(vd));
3166 }
3167 
fmaxnmp(const VRegister & vd,const VRegister & vn)3168 void Assembler::fmaxnmp(const VRegister& vd, const VRegister& vn) {
3169   DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3170   Emit(FPFormat(vd) | NEON_FMAXNMP_scalar | Rn(vn) | Rd(vd));
3171 }
3172 
fminnmp(const VRegister & vd,const VRegister & vn)3173 void Assembler::fminnmp(const VRegister& vd, const VRegister& vn) {
3174   DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3175   Emit(FPFormat(vd) | NEON_FMINNMP_scalar | Rn(vn) | Rd(vd));
3176 }
3177 
orr(const VRegister & vd,const int imm8,const int left_shift)3178 void Assembler::orr(const VRegister& vd, const int imm8, const int left_shift) {
3179   NEONModifiedImmShiftLsl(vd, imm8, left_shift, NEONModifiedImmediate_ORR);
3180 }
3181 
mov(const VRegister & vd,const VRegister & vn)3182 void Assembler::mov(const VRegister& vd, const VRegister& vn) {
3183   DCHECK(AreSameFormat(vd, vn));
3184   if (vd.IsD()) {
3185     orr(vd.V8B(), vn.V8B(), vn.V8B());
3186   } else {
3187     DCHECK(vd.IsQ());
3188     orr(vd.V16B(), vn.V16B(), vn.V16B());
3189   }
3190 }
3191 
bic(const VRegister & vd,const int imm8,const int left_shift)3192 void Assembler::bic(const VRegister& vd, const int imm8, const int left_shift) {
3193   NEONModifiedImmShiftLsl(vd, imm8, left_shift, NEONModifiedImmediate_BIC);
3194 }
3195 
movi(const VRegister & vd,const uint64_t imm,Shift shift,const int shift_amount)3196 void Assembler::movi(const VRegister& vd, const uint64_t imm, Shift shift,
3197                      const int shift_amount) {
3198   DCHECK((shift == LSL) || (shift == MSL));
3199   if (vd.Is2D() || vd.Is1D()) {
3200     DCHECK_EQ(shift_amount, 0);
3201     int imm8 = 0;
3202     for (int i = 0; i < 8; ++i) {
3203       int byte = (imm >> (i * 8)) & 0xFF;
3204       DCHECK((byte == 0) || (byte == 0xFF));
3205       if (byte == 0xFF) {
3206         imm8 |= (1 << i);
3207       }
3208     }
3209     Instr q = vd.Is2D() ? NEON_Q : 0;
3210     Emit(q | NEONModImmOp(1) | NEONModifiedImmediate_MOVI |
3211          ImmNEONabcdefgh(imm8) | NEONCmode(0xE) | Rd(vd));
3212   } else if (shift == LSL) {
3213     DCHECK(is_uint8(imm));
3214     NEONModifiedImmShiftLsl(vd, static_cast<int>(imm), shift_amount,
3215                             NEONModifiedImmediate_MOVI);
3216   } else {
3217     DCHECK(is_uint8(imm));
3218     NEONModifiedImmShiftMsl(vd, static_cast<int>(imm), shift_amount,
3219                             NEONModifiedImmediate_MOVI);
3220   }
3221 }
3222 
mvn(const VRegister & vd,const VRegister & vn)3223 void Assembler::mvn(const VRegister& vd, const VRegister& vn) {
3224   DCHECK(AreSameFormat(vd, vn));
3225   if (vd.IsD()) {
3226     not_(vd.V8B(), vn.V8B());
3227   } else {
3228     DCHECK(vd.IsQ());
3229     not_(vd.V16B(), vn.V16B());
3230   }
3231 }
3232 
mvni(const VRegister & vd,const int imm8,Shift shift,const int shift_amount)3233 void Assembler::mvni(const VRegister& vd, const int imm8, Shift shift,
3234                      const int shift_amount) {
3235   DCHECK((shift == LSL) || (shift == MSL));
3236   if (shift == LSL) {
3237     NEONModifiedImmShiftLsl(vd, imm8, shift_amount, NEONModifiedImmediate_MVNI);
3238   } else {
3239     NEONModifiedImmShiftMsl(vd, imm8, shift_amount, NEONModifiedImmediate_MVNI);
3240   }
3241 }
3242 
NEONFPByElement(const VRegister & vd,const VRegister & vn,const VRegister & vm,int vm_index,NEONByIndexedElementOp vop)3243 void Assembler::NEONFPByElement(const VRegister& vd, const VRegister& vn,
3244                                 const VRegister& vm, int vm_index,
3245                                 NEONByIndexedElementOp vop) {
3246   DCHECK(AreSameFormat(vd, vn));
3247   DCHECK((vd.Is2S() && vm.Is1S()) || (vd.Is4S() && vm.Is1S()) ||
3248          (vd.Is1S() && vm.Is1S()) || (vd.Is2D() && vm.Is1D()) ||
3249          (vd.Is1D() && vm.Is1D()));
3250   DCHECK((vm.Is1S() && (vm_index < 4)) || (vm.Is1D() && (vm_index < 2)));
3251 
3252   Instr op = vop;
3253   int index_num_bits = vm.Is1S() ? 2 : 1;
3254   if (vd.IsScalar()) {
3255     op |= NEON_Q | NEONScalar;
3256   }
3257 
3258   Emit(FPFormat(vd) | op | ImmNEONHLM(vm_index, index_num_bits) | Rm(vm) |
3259        Rn(vn) | Rd(vd));
3260 }
3261 
NEONByElement(const VRegister & vd,const VRegister & vn,const VRegister & vm,int vm_index,NEONByIndexedElementOp vop)3262 void Assembler::NEONByElement(const VRegister& vd, const VRegister& vn,
3263                               const VRegister& vm, int vm_index,
3264                               NEONByIndexedElementOp vop) {
3265   DCHECK(AreSameFormat(vd, vn));
3266   DCHECK((vd.Is4H() && vm.Is1H()) || (vd.Is8H() && vm.Is1H()) ||
3267          (vd.Is1H() && vm.Is1H()) || (vd.Is2S() && vm.Is1S()) ||
3268          (vd.Is4S() && vm.Is1S()) || (vd.Is1S() && vm.Is1S()));
3269   DCHECK((vm.Is1H() && (vm.code() < 16) && (vm_index < 8)) ||
3270          (vm.Is1S() && (vm_index < 4)));
3271 
3272   Instr format, op = vop;
3273   int index_num_bits = vm.Is1H() ? 3 : 2;
3274   if (vd.IsScalar()) {
3275     op |= NEONScalar | NEON_Q;
3276     format = SFormat(vn);
3277   } else {
3278     format = VFormat(vn);
3279   }
3280   Emit(format | op | ImmNEONHLM(vm_index, index_num_bits) | Rm(vm) | Rn(vn) |
3281        Rd(vd));
3282 }
3283 
NEONByElementL(const VRegister & vd,const VRegister & vn,const VRegister & vm,int vm_index,NEONByIndexedElementOp vop)3284 void Assembler::NEONByElementL(const VRegister& vd, const VRegister& vn,
3285                                const VRegister& vm, int vm_index,
3286                                NEONByIndexedElementOp vop) {
3287   DCHECK((vd.Is4S() && vn.Is4H() && vm.Is1H()) ||
3288          (vd.Is4S() && vn.Is8H() && vm.Is1H()) ||
3289          (vd.Is1S() && vn.Is1H() && vm.Is1H()) ||
3290          (vd.Is2D() && vn.Is2S() && vm.Is1S()) ||
3291          (vd.Is2D() && vn.Is4S() && vm.Is1S()) ||
3292          (vd.Is1D() && vn.Is1S() && vm.Is1S()));
3293 
3294   DCHECK((vm.Is1H() && (vm.code() < 16) && (vm_index < 8)) ||
3295          (vm.Is1S() && (vm_index < 4)));
3296 
3297   Instr format, op = vop;
3298   int index_num_bits = vm.Is1H() ? 3 : 2;
3299   if (vd.IsScalar()) {
3300     op |= NEONScalar | NEON_Q;
3301     format = SFormat(vn);
3302   } else {
3303     format = VFormat(vn);
3304   }
3305   Emit(format | op | ImmNEONHLM(vm_index, index_num_bits) | Rm(vm) | Rn(vn) |
3306        Rd(vd));
3307 }
3308 
3309 #define NEON_BYELEMENT_LIST(V)              \
3310   V(mul, NEON_MUL_byelement, vn.IsVector()) \
3311   V(mla, NEON_MLA_byelement, vn.IsVector()) \
3312   V(mls, NEON_MLS_byelement, vn.IsVector()) \
3313   V(sqdmulh, NEON_SQDMULH_byelement, true)  \
3314   V(sqrdmulh, NEON_SQRDMULH_byelement, true)
3315 
3316 #define DEFINE_ASM_FUNC(FN, OP, AS)                            \
3317   void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3318                      const VRegister& vm, int vm_index) {      \
3319     DCHECK(AS);                                                \
3320     NEONByElement(vd, vn, vm, vm_index, OP);                   \
3321   }
3322 NEON_BYELEMENT_LIST(DEFINE_ASM_FUNC)
3323 #undef DEFINE_ASM_FUNC
3324 
3325 #define NEON_FPBYELEMENT_LIST(V) \
3326   V(fmul, NEON_FMUL_byelement)   \
3327   V(fmla, NEON_FMLA_byelement)   \
3328   V(fmls, NEON_FMLS_byelement)   \
3329   V(fmulx, NEON_FMULX_byelement)
3330 
3331 #define DEFINE_ASM_FUNC(FN, OP)                                \
3332   void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3333                      const VRegister& vm, int vm_index) {      \
3334     NEONFPByElement(vd, vn, vm, vm_index, OP);                 \
3335   }
NEON_FPBYELEMENT_LIST(DEFINE_ASM_FUNC)3336 NEON_FPBYELEMENT_LIST(DEFINE_ASM_FUNC)
3337 #undef DEFINE_ASM_FUNC
3338 
3339 #define NEON_BYELEMENT_LONG_LIST(V)                              \
3340   V(sqdmull, NEON_SQDMULL_byelement, vn.IsScalar() || vn.IsD())  \
3341   V(sqdmull2, NEON_SQDMULL_byelement, vn.IsVector() && vn.IsQ()) \
3342   V(sqdmlal, NEON_SQDMLAL_byelement, vn.IsScalar() || vn.IsD())  \
3343   V(sqdmlal2, NEON_SQDMLAL_byelement, vn.IsVector() && vn.IsQ()) \
3344   V(sqdmlsl, NEON_SQDMLSL_byelement, vn.IsScalar() || vn.IsD())  \
3345   V(sqdmlsl2, NEON_SQDMLSL_byelement, vn.IsVector() && vn.IsQ()) \
3346   V(smull, NEON_SMULL_byelement, vn.IsVector() && vn.IsD())      \
3347   V(smull2, NEON_SMULL_byelement, vn.IsVector() && vn.IsQ())     \
3348   V(umull, NEON_UMULL_byelement, vn.IsVector() && vn.IsD())      \
3349   V(umull2, NEON_UMULL_byelement, vn.IsVector() && vn.IsQ())     \
3350   V(smlal, NEON_SMLAL_byelement, vn.IsVector() && vn.IsD())      \
3351   V(smlal2, NEON_SMLAL_byelement, vn.IsVector() && vn.IsQ())     \
3352   V(umlal, NEON_UMLAL_byelement, vn.IsVector() && vn.IsD())      \
3353   V(umlal2, NEON_UMLAL_byelement, vn.IsVector() && vn.IsQ())     \
3354   V(smlsl, NEON_SMLSL_byelement, vn.IsVector() && vn.IsD())      \
3355   V(smlsl2, NEON_SMLSL_byelement, vn.IsVector() && vn.IsQ())     \
3356   V(umlsl, NEON_UMLSL_byelement, vn.IsVector() && vn.IsD())      \
3357   V(umlsl2, NEON_UMLSL_byelement, vn.IsVector() && vn.IsQ())
3358 
3359 #define DEFINE_ASM_FUNC(FN, OP, AS)                            \
3360   void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3361                      const VRegister& vm, int vm_index) {      \
3362     DCHECK(AS);                                                \
3363     NEONByElementL(vd, vn, vm, vm_index, OP);                  \
3364   }
3365 NEON_BYELEMENT_LONG_LIST(DEFINE_ASM_FUNC)
3366 #undef DEFINE_ASM_FUNC
3367 
3368 void Assembler::suqadd(const VRegister& vd, const VRegister& vn) {
3369   NEON2RegMisc(vd, vn, NEON_SUQADD);
3370 }
3371 
usqadd(const VRegister & vd,const VRegister & vn)3372 void Assembler::usqadd(const VRegister& vd, const VRegister& vn) {
3373   NEON2RegMisc(vd, vn, NEON_USQADD);
3374 }
3375 
abs(const VRegister & vd,const VRegister & vn)3376 void Assembler::abs(const VRegister& vd, const VRegister& vn) {
3377   DCHECK(vd.IsVector() || vd.Is1D());
3378   NEON2RegMisc(vd, vn, NEON_ABS);
3379 }
3380 
sqabs(const VRegister & vd,const VRegister & vn)3381 void Assembler::sqabs(const VRegister& vd, const VRegister& vn) {
3382   NEON2RegMisc(vd, vn, NEON_SQABS);
3383 }
3384 
neg(const VRegister & vd,const VRegister & vn)3385 void Assembler::neg(const VRegister& vd, const VRegister& vn) {
3386   DCHECK(vd.IsVector() || vd.Is1D());
3387   NEON2RegMisc(vd, vn, NEON_NEG);
3388 }
3389 
sqneg(const VRegister & vd,const VRegister & vn)3390 void Assembler::sqneg(const VRegister& vd, const VRegister& vn) {
3391   NEON2RegMisc(vd, vn, NEON_SQNEG);
3392 }
3393 
NEONXtn(const VRegister & vd,const VRegister & vn,NEON2RegMiscOp vop)3394 void Assembler::NEONXtn(const VRegister& vd, const VRegister& vn,
3395                         NEON2RegMiscOp vop) {
3396   Instr format, op = vop;
3397   if (vd.IsScalar()) {
3398     DCHECK((vd.Is1B() && vn.Is1H()) || (vd.Is1H() && vn.Is1S()) ||
3399            (vd.Is1S() && vn.Is1D()));
3400     op |= NEON_Q | NEONScalar;
3401     format = SFormat(vd);
3402   } else {
3403     DCHECK((vd.Is8B() && vn.Is8H()) || (vd.Is4H() && vn.Is4S()) ||
3404            (vd.Is2S() && vn.Is2D()) || (vd.Is16B() && vn.Is8H()) ||
3405            (vd.Is8H() && vn.Is4S()) || (vd.Is4S() && vn.Is2D()));
3406     format = VFormat(vd);
3407   }
3408   Emit(format | op | Rn(vn) | Rd(vd));
3409 }
3410 
xtn(const VRegister & vd,const VRegister & vn)3411 void Assembler::xtn(const VRegister& vd, const VRegister& vn) {
3412   DCHECK(vd.IsVector() && vd.IsD());
3413   NEONXtn(vd, vn, NEON_XTN);
3414 }
3415 
xtn2(const VRegister & vd,const VRegister & vn)3416 void Assembler::xtn2(const VRegister& vd, const VRegister& vn) {
3417   DCHECK(vd.IsVector() && vd.IsQ());
3418   NEONXtn(vd, vn, NEON_XTN);
3419 }
3420 
sqxtn(const VRegister & vd,const VRegister & vn)3421 void Assembler::sqxtn(const VRegister& vd, const VRegister& vn) {
3422   DCHECK(vd.IsScalar() || vd.IsD());
3423   NEONXtn(vd, vn, NEON_SQXTN);
3424 }
3425 
sqxtn2(const VRegister & vd,const VRegister & vn)3426 void Assembler::sqxtn2(const VRegister& vd, const VRegister& vn) {
3427   DCHECK(vd.IsVector() && vd.IsQ());
3428   NEONXtn(vd, vn, NEON_SQXTN);
3429 }
3430 
sqxtun(const VRegister & vd,const VRegister & vn)3431 void Assembler::sqxtun(const VRegister& vd, const VRegister& vn) {
3432   DCHECK(vd.IsScalar() || vd.IsD());
3433   NEONXtn(vd, vn, NEON_SQXTUN);
3434 }
3435 
sqxtun2(const VRegister & vd,const VRegister & vn)3436 void Assembler::sqxtun2(const VRegister& vd, const VRegister& vn) {
3437   DCHECK(vd.IsVector() && vd.IsQ());
3438   NEONXtn(vd, vn, NEON_SQXTUN);
3439 }
3440 
uqxtn(const VRegister & vd,const VRegister & vn)3441 void Assembler::uqxtn(const VRegister& vd, const VRegister& vn) {
3442   DCHECK(vd.IsScalar() || vd.IsD());
3443   NEONXtn(vd, vn, NEON_UQXTN);
3444 }
3445 
uqxtn2(const VRegister & vd,const VRegister & vn)3446 void Assembler::uqxtn2(const VRegister& vd, const VRegister& vn) {
3447   DCHECK(vd.IsVector() && vd.IsQ());
3448   NEONXtn(vd, vn, NEON_UQXTN);
3449 }
3450 
3451 // NEON NOT and RBIT are distinguised by bit 22, the bottom bit of "size".
not_(const VRegister & vd,const VRegister & vn)3452 void Assembler::not_(const VRegister& vd, const VRegister& vn) {
3453   DCHECK(AreSameFormat(vd, vn));
3454   DCHECK(vd.Is8B() || vd.Is16B());
3455   Emit(VFormat(vd) | NEON_RBIT_NOT | Rn(vn) | Rd(vd));
3456 }
3457 
rbit(const VRegister & vd,const VRegister & vn)3458 void Assembler::rbit(const VRegister& vd, const VRegister& vn) {
3459   DCHECK(AreSameFormat(vd, vn));
3460   DCHECK(vd.Is8B() || vd.Is16B());
3461   Emit(VFormat(vn) | (1 << NEONSize_offset) | NEON_RBIT_NOT | Rn(vn) | Rd(vd));
3462 }
3463 
ext(const VRegister & vd,const VRegister & vn,const VRegister & vm,int index)3464 void Assembler::ext(const VRegister& vd, const VRegister& vn,
3465                     const VRegister& vm, int index) {
3466   DCHECK(AreSameFormat(vd, vn, vm));
3467   DCHECK(vd.Is8B() || vd.Is16B());
3468   DCHECK((0 <= index) && (index < vd.LaneCount()));
3469   Emit(VFormat(vd) | NEON_EXT | Rm(vm) | ImmNEONExt(index) | Rn(vn) | Rd(vd));
3470 }
3471 
dup(const VRegister & vd,const VRegister & vn,int vn_index)3472 void Assembler::dup(const VRegister& vd, const VRegister& vn, int vn_index) {
3473   Instr q, scalar;
3474 
3475   // We support vn arguments of the form vn.VxT() or vn.T(), where x is the
3476   // number of lanes, and T is b, h, s or d.
3477   int lane_size = vn.LaneSizeInBytes();
3478   NEONFormatField format;
3479   switch (lane_size) {
3480     case 1:
3481       format = NEON_16B;
3482       break;
3483     case 2:
3484       format = NEON_8H;
3485       break;
3486     case 4:
3487       format = NEON_4S;
3488       break;
3489     default:
3490       DCHECK_EQ(lane_size, 8);
3491       format = NEON_2D;
3492       break;
3493   }
3494 
3495   if (vd.IsScalar()) {
3496     q = NEON_Q;
3497     scalar = NEONScalar;
3498   } else {
3499     DCHECK(!vd.Is1D());
3500     q = vd.IsD() ? 0 : NEON_Q;
3501     scalar = 0;
3502   }
3503   Emit(q | scalar | NEON_DUP_ELEMENT | ImmNEON5(format, vn_index) | Rn(vn) |
3504        Rd(vd));
3505 }
3506 
dcptr(Label * label)3507 void Assembler::dcptr(Label* label) {
3508   BlockPoolsScope no_pool_inbetween(this);
3509   RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
3510   if (label->is_bound()) {
3511     // The label is bound, so it does not need to be updated and the internal
3512     // reference should be emitted.
3513     //
3514     // In this case, label->pos() returns the offset of the label from the
3515     // start of the buffer.
3516     internal_reference_positions_.push_back(pc_offset());
3517     dc64(reinterpret_cast<uintptr_t>(buffer_start_ + label->pos()));
3518   } else {
3519     int32_t offset;
3520     if (label->is_linked()) {
3521       // The label is linked, so the internal reference should be added
3522       // onto the end of the label's link chain.
3523       //
3524       // In this case, label->pos() returns the offset of the last linked
3525       // instruction from the start of the buffer.
3526       offset = label->pos() - pc_offset();
3527       DCHECK_NE(offset, kStartOfLabelLinkChain);
3528     } else {
3529       // The label is unused, so it now becomes linked and the internal
3530       // reference is at the start of the new link chain.
3531       offset = kStartOfLabelLinkChain;
3532     }
3533     // The instruction at pc is now the last link in the label's chain.
3534     label->link_to(pc_offset());
3535 
3536     // Traditionally the offset to the previous instruction in the chain is
3537     // encoded in the instruction payload (e.g. branch range) but internal
3538     // references are not instructions so while unbound they are encoded as
3539     // two consecutive brk instructions. The two 16-bit immediates are used
3540     // to encode the offset.
3541     offset >>= kInstrSizeLog2;
3542     DCHECK(is_int32(offset));
3543     uint32_t high16 = unsigned_bitextract_32(31, 16, offset);
3544     uint32_t low16 = unsigned_bitextract_32(15, 0, offset);
3545 
3546     brk(high16);
3547     brk(low16);
3548   }
3549 }
3550 
3551 // Below, a difference in case for the same letter indicates a
3552 // negated bit. If b is 1, then B is 0.
FPToImm8(double imm)3553 uint32_t Assembler::FPToImm8(double imm) {
3554   DCHECK(IsImmFP64(imm));
3555   // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
3556   //       0000.0000.0000.0000.0000.0000.0000.0000
3557   uint64_t bits = bit_cast<uint64_t>(imm);
3558   // bit7: a000.0000
3559   uint64_t bit7 = ((bits >> 63) & 0x1) << 7;
3560   // bit6: 0b00.0000
3561   uint64_t bit6 = ((bits >> 61) & 0x1) << 6;
3562   // bit5_to_0: 00cd.efgh
3563   uint64_t bit5_to_0 = (bits >> 48) & 0x3F;
3564 
3565   return static_cast<uint32_t>(bit7 | bit6 | bit5_to_0);
3566 }
3567 
ImmFP(double imm)3568 Instr Assembler::ImmFP(double imm) { return FPToImm8(imm) << ImmFP_offset; }
ImmNEONFP(double imm)3569 Instr Assembler::ImmNEONFP(double imm) {
3570   return ImmNEONabcdefgh(FPToImm8(imm));
3571 }
3572 
3573 // Code generation helpers.
MoveWide(const Register & rd,uint64_t imm,int shift,MoveWideImmediateOp mov_op)3574 void Assembler::MoveWide(const Register& rd, uint64_t imm, int shift,
3575                          MoveWideImmediateOp mov_op) {
3576   // Ignore the top 32 bits of an immediate if we're moving to a W register.
3577   if (rd.Is32Bits()) {
3578     // Check that the top 32 bits are zero (a positive 32-bit number) or top
3579     // 33 bits are one (a negative 32-bit number, sign extended to 64 bits).
3580     DCHECK(((imm >> kWRegSizeInBits) == 0) ||
3581            ((imm >> (kWRegSizeInBits - 1)) == 0x1FFFFFFFF));
3582     imm &= kWRegMask;
3583   }
3584 
3585   if (shift >= 0) {
3586     // Explicit shift specified.
3587     DCHECK((shift == 0) || (shift == 16) || (shift == 32) || (shift == 48));
3588     DCHECK(rd.Is64Bits() || (shift == 0) || (shift == 16));
3589     shift /= 16;
3590   } else {
3591     // Calculate a new immediate and shift combination to encode the immediate
3592     // argument.
3593     shift = 0;
3594     if ((imm & ~0xFFFFULL) == 0) {
3595       // Nothing to do.
3596     } else if ((imm & ~(0xFFFFULL << 16)) == 0) {
3597       imm >>= 16;
3598       shift = 1;
3599     } else if ((imm & ~(0xFFFFULL << 32)) == 0) {
3600       DCHECK(rd.Is64Bits());
3601       imm >>= 32;
3602       shift = 2;
3603     } else if ((imm & ~(0xFFFFULL << 48)) == 0) {
3604       DCHECK(rd.Is64Bits());
3605       imm >>= 48;
3606       shift = 3;
3607     }
3608   }
3609 
3610   DCHECK(is_uint16(imm));
3611 
3612   Emit(SF(rd) | MoveWideImmediateFixed | mov_op | Rd(rd) |
3613        ImmMoveWide(static_cast<int>(imm)) | ShiftMoveWide(shift));
3614 }
3615 
AddSub(const Register & rd,const Register & rn,const Operand & operand,FlagsUpdate S,AddSubOp op)3616 void Assembler::AddSub(const Register& rd, const Register& rn,
3617                        const Operand& operand, FlagsUpdate S, AddSubOp op) {
3618   DCHECK_EQ(rd.SizeInBits(), rn.SizeInBits());
3619   DCHECK(!operand.NeedsRelocation(this));
3620   if (operand.IsImmediate()) {
3621     int64_t immediate = operand.ImmediateValue();
3622     DCHECK(IsImmAddSub(immediate));
3623     Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
3624     Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) |
3625          ImmAddSub(static_cast<int>(immediate)) | dest_reg | RnSP(rn));
3626   } else if (operand.IsShiftedRegister()) {
3627     DCHECK_EQ(operand.reg().SizeInBits(), rd.SizeInBits());
3628     DCHECK_NE(operand.shift(), ROR);
3629 
3630     // For instructions of the form:
3631     //   add/sub   wsp, <Wn>, <Wm> [, LSL #0-3 ]
3632     //   add/sub   <Wd>, wsp, <Wm> [, LSL #0-3 ]
3633     //   add/sub   wsp, wsp, <Wm> [, LSL #0-3 ]
3634     //   adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ]
3635     // or their 64-bit register equivalents, convert the operand from shifted to
3636     // extended register mode, and emit an add/sub extended instruction.
3637     if (rn.IsSP() || rd.IsSP()) {
3638       DCHECK(!(rd.IsSP() && (S == SetFlags)));
3639       DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S,
3640                                AddSubExtendedFixed | op);
3641     } else {
3642       DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op);
3643     }
3644   } else {
3645     DCHECK(operand.IsExtendedRegister());
3646     DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op);
3647   }
3648 }
3649 
AddSubWithCarry(const Register & rd,const Register & rn,const Operand & operand,FlagsUpdate S,AddSubWithCarryOp op)3650 void Assembler::AddSubWithCarry(const Register& rd, const Register& rn,
3651                                 const Operand& operand, FlagsUpdate S,
3652                                 AddSubWithCarryOp op) {
3653   DCHECK_EQ(rd.SizeInBits(), rn.SizeInBits());
3654   DCHECK_EQ(rd.SizeInBits(), operand.reg().SizeInBits());
3655   DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
3656   DCHECK(!operand.NeedsRelocation(this));
3657   Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd));
3658 }
3659 
hlt(int code)3660 void Assembler::hlt(int code) {
3661   DCHECK(is_uint16(code));
3662   Emit(HLT | ImmException(code));
3663 }
3664 
brk(int code)3665 void Assembler::brk(int code) {
3666   DCHECK(is_uint16(code));
3667   Emit(BRK | ImmException(code));
3668 }
3669 
EmitStringData(const char * string)3670 void Assembler::EmitStringData(const char* string) {
3671   size_t len = strlen(string) + 1;
3672   DCHECK_LE(RoundUp(len, kInstrSize), static_cast<size_t>(kGap));
3673   EmitData(string, static_cast<int>(len));
3674   // Pad with nullptr characters until pc_ is aligned.
3675   const char pad[] = {'\0', '\0', '\0', '\0'};
3676   static_assert(sizeof(pad) == kInstrSize,
3677                 "Size of padding must match instruction size.");
3678   EmitData(pad, RoundUp(pc_offset(), kInstrSize) - pc_offset());
3679 }
3680 
debug(const char * message,uint32_t code,Instr params)3681 void Assembler::debug(const char* message, uint32_t code, Instr params) {
3682   if (options().enable_simulator_code) {
3683     // The arguments to the debug marker need to be contiguous in memory, so
3684     // make sure we don't try to emit pools.
3685     BlockPoolsScope scope(this);
3686 
3687     Label start;
3688     bind(&start);
3689 
3690     // Refer to instructions-arm64.h for a description of the marker and its
3691     // arguments.
3692     hlt(kImmExceptionIsDebug);
3693     DCHECK_EQ(SizeOfCodeGeneratedSince(&start), kDebugCodeOffset);
3694     dc32(code);
3695     DCHECK_EQ(SizeOfCodeGeneratedSince(&start), kDebugParamsOffset);
3696     dc32(params);
3697     DCHECK_EQ(SizeOfCodeGeneratedSince(&start), kDebugMessageOffset);
3698     EmitStringData(message);
3699     hlt(kImmExceptionIsUnreachable);
3700 
3701     return;
3702   }
3703 
3704   if (params & BREAK) {
3705     brk(0);
3706   }
3707 }
3708 
Logical(const Register & rd,const Register & rn,const Operand & operand,LogicalOp op)3709 void Assembler::Logical(const Register& rd, const Register& rn,
3710                         const Operand& operand, LogicalOp op) {
3711   DCHECK(rd.SizeInBits() == rn.SizeInBits());
3712   DCHECK(!operand.NeedsRelocation(this));
3713   if (operand.IsImmediate()) {
3714     int64_t immediate = operand.ImmediateValue();
3715     unsigned reg_size = rd.SizeInBits();
3716 
3717     DCHECK_NE(immediate, 0);
3718     DCHECK_NE(immediate, -1);
3719     DCHECK(rd.Is64Bits() || is_uint32(immediate));
3720 
3721     // If the operation is NOT, invert the operation and immediate.
3722     if ((op & NOT) == NOT) {
3723       op = static_cast<LogicalOp>(op & ~NOT);
3724       immediate = rd.Is64Bits() ? ~immediate : (~immediate & kWRegMask);
3725     }
3726 
3727     unsigned n, imm_s, imm_r;
3728     if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
3729       // Immediate can be encoded in the instruction.
3730       LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
3731     } else {
3732       // This case is handled in the macro assembler.
3733       UNREACHABLE();
3734     }
3735   } else {
3736     DCHECK(operand.IsShiftedRegister());
3737     DCHECK(operand.reg().SizeInBits() == rd.SizeInBits());
3738     Instr dp_op = static_cast<Instr>(op | LogicalShiftedFixed);
3739     DataProcShiftedRegister(rd, rn, operand, LeaveFlags, dp_op);
3740   }
3741 }
3742 
LogicalImmediate(const Register & rd,const Register & rn,unsigned n,unsigned imm_s,unsigned imm_r,LogicalOp op)3743 void Assembler::LogicalImmediate(const Register& rd, const Register& rn,
3744                                  unsigned n, unsigned imm_s, unsigned imm_r,
3745                                  LogicalOp op) {
3746   unsigned reg_size = rd.SizeInBits();
3747   Instr dest_reg = (op == ANDS) ? Rd(rd) : RdSP(rd);
3748   Emit(SF(rd) | LogicalImmediateFixed | op | BitN(n, reg_size) |
3749        ImmSetBits(imm_s, reg_size) | ImmRotate(imm_r, reg_size) | dest_reg |
3750        Rn(rn));
3751 }
3752 
ConditionalCompare(const Register & rn,const Operand & operand,StatusFlags nzcv,Condition cond,ConditionalCompareOp op)3753 void Assembler::ConditionalCompare(const Register& rn, const Operand& operand,
3754                                    StatusFlags nzcv, Condition cond,
3755                                    ConditionalCompareOp op) {
3756   Instr ccmpop;
3757   DCHECK(!operand.NeedsRelocation(this));
3758   if (operand.IsImmediate()) {
3759     int64_t immediate = operand.ImmediateValue();
3760     DCHECK(IsImmConditionalCompare(immediate));
3761     ccmpop = ConditionalCompareImmediateFixed | op |
3762              ImmCondCmp(static_cast<unsigned>(immediate));
3763   } else {
3764     DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
3765     ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg());
3766   }
3767   Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv));
3768 }
3769 
DataProcessing1Source(const Register & rd,const Register & rn,DataProcessing1SourceOp op)3770 void Assembler::DataProcessing1Source(const Register& rd, const Register& rn,
3771                                       DataProcessing1SourceOp op) {
3772   DCHECK(rd.SizeInBits() == rn.SizeInBits());
3773   Emit(SF(rn) | op | Rn(rn) | Rd(rd));
3774 }
3775 
FPDataProcessing1Source(const VRegister & vd,const VRegister & vn,FPDataProcessing1SourceOp op)3776 void Assembler::FPDataProcessing1Source(const VRegister& vd,
3777                                         const VRegister& vn,
3778                                         FPDataProcessing1SourceOp op) {
3779   Emit(FPType(vn) | op | Rn(vn) | Rd(vd));
3780 }
3781 
FPDataProcessing2Source(const VRegister & fd,const VRegister & fn,const VRegister & fm,FPDataProcessing2SourceOp op)3782 void Assembler::FPDataProcessing2Source(const VRegister& fd,
3783                                         const VRegister& fn,
3784                                         const VRegister& fm,
3785                                         FPDataProcessing2SourceOp op) {
3786   DCHECK(fd.SizeInBits() == fn.SizeInBits());
3787   DCHECK(fd.SizeInBits() == fm.SizeInBits());
3788   Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd));
3789 }
3790 
FPDataProcessing3Source(const VRegister & fd,const VRegister & fn,const VRegister & fm,const VRegister & fa,FPDataProcessing3SourceOp op)3791 void Assembler::FPDataProcessing3Source(const VRegister& fd,
3792                                         const VRegister& fn,
3793                                         const VRegister& fm,
3794                                         const VRegister& fa,
3795                                         FPDataProcessing3SourceOp op) {
3796   DCHECK(AreSameSizeAndType(fd, fn, fm, fa));
3797   Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa));
3798 }
3799 
NEONModifiedImmShiftLsl(const VRegister & vd,const int imm8,const int left_shift,NEONModifiedImmediateOp op)3800 void Assembler::NEONModifiedImmShiftLsl(const VRegister& vd, const int imm8,
3801                                         const int left_shift,
3802                                         NEONModifiedImmediateOp op) {
3803   DCHECK(vd.Is8B() || vd.Is16B() || vd.Is4H() || vd.Is8H() || vd.Is2S() ||
3804          vd.Is4S());
3805   DCHECK((left_shift == 0) || (left_shift == 8) || (left_shift == 16) ||
3806          (left_shift == 24));
3807   DCHECK(is_uint8(imm8));
3808 
3809   int cmode_1, cmode_2, cmode_3;
3810   if (vd.Is8B() || vd.Is16B()) {
3811     DCHECK_EQ(op, NEONModifiedImmediate_MOVI);
3812     cmode_1 = 1;
3813     cmode_2 = 1;
3814     cmode_3 = 1;
3815   } else {
3816     cmode_1 = (left_shift >> 3) & 1;
3817     cmode_2 = left_shift >> 4;
3818     cmode_3 = 0;
3819     if (vd.Is4H() || vd.Is8H()) {
3820       DCHECK((left_shift == 0) || (left_shift == 8));
3821       cmode_3 = 1;
3822     }
3823   }
3824   int cmode = (cmode_3 << 3) | (cmode_2 << 2) | (cmode_1 << 1);
3825 
3826   Instr q = vd.IsQ() ? NEON_Q : 0;
3827 
3828   Emit(q | op | ImmNEONabcdefgh(imm8) | NEONCmode(cmode) | Rd(vd));
3829 }
3830 
NEONModifiedImmShiftMsl(const VRegister & vd,const int imm8,const int shift_amount,NEONModifiedImmediateOp op)3831 void Assembler::NEONModifiedImmShiftMsl(const VRegister& vd, const int imm8,
3832                                         const int shift_amount,
3833                                         NEONModifiedImmediateOp op) {
3834   DCHECK(vd.Is2S() || vd.Is4S());
3835   DCHECK((shift_amount == 8) || (shift_amount == 16));
3836   DCHECK(is_uint8(imm8));
3837 
3838   int cmode_0 = (shift_amount >> 4) & 1;
3839   int cmode = 0xC | cmode_0;
3840 
3841   Instr q = vd.IsQ() ? NEON_Q : 0;
3842 
3843   Emit(q | op | ImmNEONabcdefgh(imm8) | NEONCmode(cmode) | Rd(vd));
3844 }
3845 
EmitShift(const Register & rd,const Register & rn,Shift shift,unsigned shift_amount)3846 void Assembler::EmitShift(const Register& rd, const Register& rn, Shift shift,
3847                           unsigned shift_amount) {
3848   switch (shift) {
3849     case LSL:
3850       lsl(rd, rn, shift_amount);
3851       break;
3852     case LSR:
3853       lsr(rd, rn, shift_amount);
3854       break;
3855     case ASR:
3856       asr(rd, rn, shift_amount);
3857       break;
3858     case ROR:
3859       ror(rd, rn, shift_amount);
3860       break;
3861     default:
3862       UNREACHABLE();
3863   }
3864 }
3865 
EmitExtendShift(const Register & rd,const Register & rn,Extend extend,unsigned left_shift)3866 void Assembler::EmitExtendShift(const Register& rd, const Register& rn,
3867                                 Extend extend, unsigned left_shift) {
3868   DCHECK(rd.SizeInBits() >= rn.SizeInBits());
3869   unsigned reg_size = rd.SizeInBits();
3870   // Use the correct size of register.
3871   Register rn_ = Register::Create(rn.code(), rd.SizeInBits());
3872   // Bits extracted are high_bit:0.
3873   unsigned high_bit = (8 << (extend & 0x3)) - 1;
3874   // Number of bits left in the result that are not introduced by the shift.
3875   unsigned non_shift_bits = (reg_size - left_shift) & (reg_size - 1);
3876 
3877   if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) {
3878     switch (extend) {
3879       case UXTB:
3880       case UXTH:
3881       case UXTW:
3882         ubfm(rd, rn_, non_shift_bits, high_bit);
3883         break;
3884       case SXTB:
3885       case SXTH:
3886       case SXTW:
3887         sbfm(rd, rn_, non_shift_bits, high_bit);
3888         break;
3889       case UXTX:
3890       case SXTX: {
3891         DCHECK_EQ(rn.SizeInBits(), kXRegSizeInBits);
3892         // Nothing to extend. Just shift.
3893         lsl(rd, rn_, left_shift);
3894         break;
3895       }
3896       default:
3897         UNREACHABLE();
3898     }
3899   } else {
3900     // No need to extend as the extended bits would be shifted away.
3901     lsl(rd, rn_, left_shift);
3902   }
3903 }
3904 
DataProcShiftedRegister(const Register & rd,const Register & rn,const Operand & operand,FlagsUpdate S,Instr op)3905 void Assembler::DataProcShiftedRegister(const Register& rd, const Register& rn,
3906                                         const Operand& operand, FlagsUpdate S,
3907                                         Instr op) {
3908   DCHECK(operand.IsShiftedRegister());
3909   DCHECK(rn.Is64Bits() || (rn.Is32Bits() && is_uint5(operand.shift_amount())));
3910   DCHECK(!operand.NeedsRelocation(this));
3911   Emit(SF(rd) | op | Flags(S) | ShiftDP(operand.shift()) |
3912        ImmDPShift(operand.shift_amount()) | Rm(operand.reg()) | Rn(rn) |
3913        Rd(rd));
3914 }
3915 
DataProcExtendedRegister(const Register & rd,const Register & rn,const Operand & operand,FlagsUpdate S,Instr op)3916 void Assembler::DataProcExtendedRegister(const Register& rd, const Register& rn,
3917                                          const Operand& operand, FlagsUpdate S,
3918                                          Instr op) {
3919   DCHECK(!operand.NeedsRelocation(this));
3920   Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
3921   Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) |
3922        ExtendMode(operand.extend()) | ImmExtendShift(operand.shift_amount()) |
3923        dest_reg | RnSP(rn));
3924 }
3925 
IsImmAddSub(int64_t immediate)3926 bool Assembler::IsImmAddSub(int64_t immediate) {
3927   return is_uint12(immediate) ||
3928          (is_uint12(immediate >> 12) && ((immediate & 0xFFF) == 0));
3929 }
3930 
LoadStore(const CPURegister & rt,const MemOperand & addr,LoadStoreOp op)3931 void Assembler::LoadStore(const CPURegister& rt, const MemOperand& addr,
3932                           LoadStoreOp op) {
3933   Instr memop = op | Rt(rt) | RnSP(addr.base());
3934 
3935   if (addr.IsImmediateOffset()) {
3936     unsigned size = CalcLSDataSize(op);
3937     if (IsImmLSScaled(addr.offset(), size)) {
3938       int offset = static_cast<int>(addr.offset());
3939       // Use the scaled addressing mode.
3940       Emit(LoadStoreUnsignedOffsetFixed | memop |
3941            ImmLSUnsigned(offset >> size));
3942     } else if (IsImmLSUnscaled(addr.offset())) {
3943       int offset = static_cast<int>(addr.offset());
3944       // Use the unscaled addressing mode.
3945       Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset));
3946     } else {
3947       // This case is handled in the macro assembler.
3948       UNREACHABLE();
3949     }
3950   } else if (addr.IsRegisterOffset()) {
3951     Extend ext = addr.extend();
3952     Shift shift = addr.shift();
3953     unsigned shift_amount = addr.shift_amount();
3954 
3955     // LSL is encoded in the option field as UXTX.
3956     if (shift == LSL) {
3957       ext = UXTX;
3958     }
3959 
3960     // Shifts are encoded in one bit, indicating a left shift by the memory
3961     // access size.
3962     DCHECK((shift_amount == 0) ||
3963            (shift_amount == static_cast<unsigned>(CalcLSDataSize(op))));
3964     Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) |
3965          ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0));
3966   } else {
3967     // Pre-index and post-index modes.
3968     DCHECK_NE(rt, addr.base());
3969     if (IsImmLSUnscaled(addr.offset())) {
3970       int offset = static_cast<int>(addr.offset());
3971       if (addr.IsPreIndex()) {
3972         Emit(LoadStorePreIndexFixed | memop | ImmLS(offset));
3973       } else {
3974         DCHECK(addr.IsPostIndex());
3975         Emit(LoadStorePostIndexFixed | memop | ImmLS(offset));
3976       }
3977     } else {
3978       // This case is handled in the macro assembler.
3979       UNREACHABLE();
3980     }
3981   }
3982 }
3983 
IsImmLSUnscaled(int64_t offset)3984 bool Assembler::IsImmLSUnscaled(int64_t offset) { return is_int9(offset); }
3985 
IsImmLSScaled(int64_t offset,unsigned size)3986 bool Assembler::IsImmLSScaled(int64_t offset, unsigned size) {
3987   bool offset_is_size_multiple =
3988       (static_cast<int64_t>(static_cast<uint64_t>(offset >> size) << size) ==
3989        offset);
3990   return offset_is_size_multiple && is_uint12(offset >> size);
3991 }
3992 
IsImmLSPair(int64_t offset,unsigned size)3993 bool Assembler::IsImmLSPair(int64_t offset, unsigned size) {
3994   bool offset_is_size_multiple =
3995       (static_cast<int64_t>(static_cast<uint64_t>(offset >> size) << size) ==
3996        offset);
3997   return offset_is_size_multiple && is_int7(offset >> size);
3998 }
3999 
IsImmLLiteral(int64_t offset)4000 bool Assembler::IsImmLLiteral(int64_t offset) {
4001   int inst_size = static_cast<int>(kInstrSizeLog2);
4002   bool offset_is_inst_multiple =
4003       (static_cast<int64_t>(static_cast<uint64_t>(offset >> inst_size)
4004                             << inst_size) == offset);
4005   DCHECK_GT(offset, 0);
4006   offset >>= kLoadLiteralScaleLog2;
4007   return offset_is_inst_multiple && is_intn(offset, ImmLLiteral_width);
4008 }
4009 
4010 // Test if a given value can be encoded in the immediate field of a logical
4011 // instruction.
4012 // If it can be encoded, the function returns true, and values pointed to by n,
4013 // imm_s and imm_r are updated with immediates encoded in the format required
4014 // by the corresponding fields in the logical instruction.
4015 // If it can not be encoded, the function returns false, and the values pointed
4016 // to by n, imm_s and imm_r are undefined.
IsImmLogical(uint64_t value,unsigned width,unsigned * n,unsigned * imm_s,unsigned * imm_r)4017 bool Assembler::IsImmLogical(uint64_t value, unsigned width, unsigned* n,
4018                              unsigned* imm_s, unsigned* imm_r) {
4019   DCHECK((n != nullptr) && (imm_s != nullptr) && (imm_r != nullptr));
4020   DCHECK((width == kWRegSizeInBits) || (width == kXRegSizeInBits));
4021 
4022   bool negate = false;
4023 
4024   // Logical immediates are encoded using parameters n, imm_s and imm_r using
4025   // the following table:
4026   //
4027   //    N   imms    immr    size        S             R
4028   //    1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
4029   //    0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
4030   //    0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
4031   //    0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
4032   //    0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
4033   //    0  11110s  xxxxxr     2    UInt(s)       UInt(r)
4034   // (s bits must not be all set)
4035   //
4036   // A pattern is constructed of size bits, where the least significant S+1 bits
4037   // are set. The pattern is rotated right by R, and repeated across a 32 or
4038   // 64-bit value, depending on destination register width.
4039   //
4040   // Put another way: the basic format of a logical immediate is a single
4041   // contiguous stretch of 1 bits, repeated across the whole word at intervals
4042   // given by a power of 2. To identify them quickly, we first locate the
4043   // lowest stretch of 1 bits, then the next 1 bit above that; that combination
4044   // is different for every logical immediate, so it gives us all the
4045   // information we need to identify the only logical immediate that our input
4046   // could be, and then we simply check if that's the value we actually have.
4047   //
4048   // (The rotation parameter does give the possibility of the stretch of 1 bits
4049   // going 'round the end' of the word. To deal with that, we observe that in
4050   // any situation where that happens the bitwise NOT of the value is also a
4051   // valid logical immediate. So we simply invert the input whenever its low bit
4052   // is set, and then we know that the rotated case can't arise.)
4053 
4054   if (value & 1) {
4055     // If the low bit is 1, negate the value, and set a flag to remember that we
4056     // did (so that we can adjust the return values appropriately).
4057     negate = true;
4058     value = ~value;
4059   }
4060 
4061   if (width == kWRegSizeInBits) {
4062     // To handle 32-bit logical immediates, the very easiest thing is to repeat
4063     // the input value twice to make a 64-bit word. The correct encoding of that
4064     // as a logical immediate will also be the correct encoding of the 32-bit
4065     // value.
4066 
4067     // The most-significant 32 bits may not be zero (ie. negate is true) so
4068     // shift the value left before duplicating it.
4069     value <<= kWRegSizeInBits;
4070     value |= value >> kWRegSizeInBits;
4071   }
4072 
4073   // The basic analysis idea: imagine our input word looks like this.
4074   //
4075   //    0011111000111110001111100011111000111110001111100011111000111110
4076   //                                                          c  b    a
4077   //                                                          |<--d-->|
4078   //
4079   // We find the lowest set bit (as an actual power-of-2 value, not its index)
4080   // and call it a. Then we add a to our original number, which wipes out the
4081   // bottommost stretch of set bits and replaces it with a 1 carried into the
4082   // next zero bit. Then we look for the new lowest set bit, which is in
4083   // position b, and subtract it, so now our number is just like the original
4084   // but with the lowest stretch of set bits completely gone. Now we find the
4085   // lowest set bit again, which is position c in the diagram above. Then we'll
4086   // measure the distance d between bit positions a and c (using CLZ), and that
4087   // tells us that the only valid logical immediate that could possibly be equal
4088   // to this number is the one in which a stretch of bits running from a to just
4089   // below b is replicated every d bits.
4090   uint64_t a = LargestPowerOf2Divisor(value);
4091   uint64_t value_plus_a = value + a;
4092   uint64_t b = LargestPowerOf2Divisor(value_plus_a);
4093   uint64_t value_plus_a_minus_b = value_plus_a - b;
4094   uint64_t c = LargestPowerOf2Divisor(value_plus_a_minus_b);
4095 
4096   int d, clz_a, out_n;
4097   uint64_t mask;
4098 
4099   if (c != 0) {
4100     // The general case, in which there is more than one stretch of set bits.
4101     // Compute the repeat distance d, and set up a bitmask covering the basic
4102     // unit of repetition (i.e. a word with the bottom d bits set). Also, in all
4103     // of these cases the N bit of the output will be zero.
4104     clz_a = CountLeadingZeros(a, kXRegSizeInBits);
4105     int clz_c = CountLeadingZeros(c, kXRegSizeInBits);
4106     d = clz_a - clz_c;
4107     mask = ((uint64_t{1} << d) - 1);
4108     out_n = 0;
4109   } else {
4110     // Handle degenerate cases.
4111     //
4112     // If any of those 'find lowest set bit' operations didn't find a set bit at
4113     // all, then the word will have been zero thereafter, so in particular the
4114     // last lowest_set_bit operation will have returned zero. So we can test for
4115     // all the special case conditions in one go by seeing if c is zero.
4116     if (a == 0) {
4117       // The input was zero (or all 1 bits, which will come to here too after we
4118       // inverted it at the start of the function), for which we just return
4119       // false.
4120       return false;
4121     } else {
4122       // Otherwise, if c was zero but a was not, then there's just one stretch
4123       // of set bits in our word, meaning that we have the trivial case of
4124       // d == 64 and only one 'repetition'. Set up all the same variables as in
4125       // the general case above, and set the N bit in the output.
4126       clz_a = CountLeadingZeros(a, kXRegSizeInBits);
4127       d = 64;
4128       mask = ~uint64_t{0};
4129       out_n = 1;
4130     }
4131   }
4132 
4133   // If the repeat period d is not a power of two, it can't be encoded.
4134   if (!base::bits::IsPowerOfTwo(d)) {
4135     return false;
4136   }
4137 
4138   if (((b - a) & ~mask) != 0) {
4139     // If the bit stretch (b - a) does not fit within the mask derived from the
4140     // repeat period, then fail.
4141     return false;
4142   }
4143 
4144   // The only possible option is b - a repeated every d bits. Now we're going to
4145   // actually construct the valid logical immediate derived from that
4146   // specification, and see if it equals our original input.
4147   //
4148   // To repeat a value every d bits, we multiply it by a number of the form
4149   // (1 + 2^d + 2^(2d) + ...), i.e. 0x0001000100010001 or similar. These can
4150   // be derived using a table lookup on CLZ(d).
4151   static const uint64_t multipliers[] = {
4152       0x0000000000000001UL, 0x0000000100000001UL, 0x0001000100010001UL,
4153       0x0101010101010101UL, 0x1111111111111111UL, 0x5555555555555555UL,
4154   };
4155   int multiplier_idx = CountLeadingZeros(d, kXRegSizeInBits) - 57;
4156   // Ensure that the index to the multipliers array is within bounds.
4157   DCHECK((multiplier_idx >= 0) &&
4158          (static_cast<size_t>(multiplier_idx) < arraysize(multipliers)));
4159   uint64_t multiplier = multipliers[multiplier_idx];
4160   uint64_t candidate = (b - a) * multiplier;
4161 
4162   if (value != candidate) {
4163     // The candidate pattern doesn't match our input value, so fail.
4164     return false;
4165   }
4166 
4167   // We have a match! This is a valid logical immediate, so now we have to
4168   // construct the bits and pieces of the instruction encoding that generates
4169   // it.
4170 
4171   // Count the set bits in our basic stretch. The special case of clz(0) == -1
4172   // makes the answer come out right for stretches that reach the very top of
4173   // the word (e.g. numbers like 0xFFFFC00000000000).
4174   int clz_b = (b == 0) ? -1 : CountLeadingZeros(b, kXRegSizeInBits);
4175   int s = clz_a - clz_b;
4176 
4177   // Decide how many bits to rotate right by, to put the low bit of that basic
4178   // stretch in position a.
4179   int r;
4180   if (negate) {
4181     // If we inverted the input right at the start of this function, here's
4182     // where we compensate: the number of set bits becomes the number of clear
4183     // bits, and the rotation count is based on position b rather than position
4184     // a (since b is the location of the 'lowest' 1 bit after inversion).
4185     s = d - s;
4186     r = (clz_b + 1) & (d - 1);
4187   } else {
4188     r = (clz_a + 1) & (d - 1);
4189   }
4190 
4191   // Now we're done, except for having to encode the S output in such a way that
4192   // it gives both the number of set bits and the length of the repeated
4193   // segment. The s field is encoded like this:
4194   //
4195   //     imms    size        S
4196   //    ssssss    64    UInt(ssssss)
4197   //    0sssss    32    UInt(sssss)
4198   //    10ssss    16    UInt(ssss)
4199   //    110sss     8    UInt(sss)
4200   //    1110ss     4    UInt(ss)
4201   //    11110s     2    UInt(s)
4202   //
4203   // So we 'or' (-d * 2) with our computed s to form imms.
4204   *n = out_n;
4205   *imm_s = ((-d * 2) | (s - 1)) & 0x3F;
4206   *imm_r = r;
4207 
4208   return true;
4209 }
4210 
IsImmConditionalCompare(int64_t immediate)4211 bool Assembler::IsImmConditionalCompare(int64_t immediate) {
4212   return is_uint5(immediate);
4213 }
4214 
IsImmFP32(float imm)4215 bool Assembler::IsImmFP32(float imm) {
4216   // Valid values will have the form:
4217   // aBbb.bbbc.defg.h000.0000.0000.0000.0000
4218   uint32_t bits = bit_cast<uint32_t>(imm);
4219   // bits[19..0] are cleared.
4220   if ((bits & 0x7FFFF) != 0) {
4221     return false;
4222   }
4223 
4224   // bits[29..25] are all set or all cleared.
4225   uint32_t b_pattern = (bits >> 16) & 0x3E00;
4226   if (b_pattern != 0 && b_pattern != 0x3E00) {
4227     return false;
4228   }
4229 
4230   // bit[30] and bit[29] are opposite.
4231   if (((bits ^ (bits << 1)) & 0x40000000) == 0) {
4232     return false;
4233   }
4234 
4235   return true;
4236 }
4237 
IsImmFP64(double imm)4238 bool Assembler::IsImmFP64(double imm) {
4239   // Valid values will have the form:
4240   // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
4241   // 0000.0000.0000.0000.0000.0000.0000.0000
4242   uint64_t bits = bit_cast<uint64_t>(imm);
4243   // bits[47..0] are cleared.
4244   if ((bits & 0xFFFFFFFFFFFFL) != 0) {
4245     return false;
4246   }
4247 
4248   // bits[61..54] are all set or all cleared.
4249   uint32_t b_pattern = (bits >> 48) & 0x3FC0;
4250   if (b_pattern != 0 && b_pattern != 0x3FC0) {
4251     return false;
4252   }
4253 
4254   // bit[62] and bit[61] are opposite.
4255   if (((bits ^ (bits << 1)) & 0x4000000000000000L) == 0) {
4256     return false;
4257   }
4258 
4259   return true;
4260 }
4261 
GrowBuffer()4262 void Assembler::GrowBuffer() {
4263   // Compute new buffer size.
4264   int old_size = buffer_->size();
4265   int new_size = std::min(2 * old_size, old_size + 1 * MB);
4266 
4267   // Some internal data structures overflow for very large buffers,
4268   // they must ensure that kMaximalBufferSize is not too large.
4269   if (new_size > kMaximalBufferSize) {
4270     V8::FatalProcessOutOfMemory(nullptr, "Assembler::GrowBuffer");
4271   }
4272 
4273   // Set up new buffer.
4274   std::unique_ptr<AssemblerBuffer> new_buffer = buffer_->Grow(new_size);
4275   DCHECK_EQ(new_size, new_buffer->size());
4276   byte* new_start = new_buffer->start();
4277 
4278   // Copy the data.
4279   intptr_t pc_delta = new_start - buffer_start_;
4280   intptr_t rc_delta = (new_start + new_size) - (buffer_start_ + old_size);
4281   size_t reloc_size = (buffer_start_ + old_size) - reloc_info_writer.pos();
4282   memmove(new_start, buffer_start_, pc_offset());
4283   memmove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
4284           reloc_size);
4285 
4286   // Switch buffers.
4287   buffer_ = std::move(new_buffer);
4288   buffer_start_ = new_start;
4289   pc_ += pc_delta;
4290   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
4291                                reloc_info_writer.last_pc() + pc_delta);
4292 
4293   // None of our relocation types are pc relative pointing outside the code
4294   // buffer nor pc absolute pointing inside the code buffer, so there is no need
4295   // to relocate any emitted relocation entries.
4296 
4297   // Relocate internal references.
4298   for (auto pos : internal_reference_positions_) {
4299     Address address = reinterpret_cast<intptr_t>(buffer_start_) + pos;
4300     intptr_t internal_ref = ReadUnalignedValue<intptr_t>(address);
4301     internal_ref += pc_delta;
4302     WriteUnalignedValue<intptr_t>(address, internal_ref);
4303   }
4304 
4305   // Pending relocation entries are also relative, no need to relocate.
4306 }
4307 
RecordRelocInfo(RelocInfo::Mode rmode,intptr_t data,ConstantPoolMode constant_pool_mode)4308 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data,
4309                                 ConstantPoolMode constant_pool_mode) {
4310   if ((rmode == RelocInfo::INTERNAL_REFERENCE) ||
4311       (rmode == RelocInfo::CONST_POOL) || (rmode == RelocInfo::VENEER_POOL) ||
4312       (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) ||
4313       (rmode == RelocInfo::DEOPT_INLINING_ID) ||
4314       (rmode == RelocInfo::DEOPT_REASON) || (rmode == RelocInfo::DEOPT_ID)) {
4315     // Adjust code for new modes.
4316     DCHECK(RelocInfo::IsDeoptReason(rmode) || RelocInfo::IsDeoptId(rmode) ||
4317            RelocInfo::IsDeoptPosition(rmode) ||
4318            RelocInfo::IsInternalReference(rmode) ||
4319            RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode));
4320     // These modes do not need an entry in the constant pool.
4321   } else if (constant_pool_mode == NEEDS_POOL_ENTRY) {
4322     if (RelocInfo::IsEmbeddedObjectMode(rmode)) {
4323       Handle<HeapObject> handle(reinterpret_cast<Address*>(data));
4324       data = AddEmbeddedObject(handle);
4325     }
4326     if (rmode == RelocInfo::COMPRESSED_EMBEDDED_OBJECT) {
4327       if (constpool_.RecordEntry(static_cast<uint32_t>(data), rmode) ==
4328           RelocInfoStatus::kMustOmitForDuplicate) {
4329         return;
4330       }
4331     } else {
4332       if (constpool_.RecordEntry(static_cast<uint64_t>(data), rmode) ==
4333           RelocInfoStatus::kMustOmitForDuplicate) {
4334         return;
4335       }
4336     }
4337   }
4338   // For modes that cannot use the constant pool, a different sequence of
4339   // instructions will be emitted by this function's caller.
4340 
4341   if (!ShouldRecordRelocInfo(rmode)) return;
4342 
4343   // Callers should ensure that constant pool emission is blocked until the
4344   // instruction the reloc info is associated with has been emitted.
4345   DCHECK(constpool_.IsBlocked());
4346 
4347   // We do not try to reuse pool constants.
4348   RelocInfo rinfo(reinterpret_cast<Address>(pc_), rmode, data, Code());
4349 
4350   DCHECK_GE(buffer_space(), kMaxRelocSize);  // too late to grow buffer here
4351   reloc_info_writer.Write(&rinfo);
4352 }
4353 
near_jump(int offset,RelocInfo::Mode rmode)4354 void Assembler::near_jump(int offset, RelocInfo::Mode rmode) {
4355   BlockPoolsScope no_pool_before_b_instr(this);
4356   if (!RelocInfo::IsNone(rmode)) RecordRelocInfo(rmode, offset, NO_POOL_ENTRY);
4357   b(offset);
4358 }
4359 
near_call(int offset,RelocInfo::Mode rmode)4360 void Assembler::near_call(int offset, RelocInfo::Mode rmode) {
4361   BlockPoolsScope no_pool_before_bl_instr(this);
4362   if (!RelocInfo::IsNone(rmode)) RecordRelocInfo(rmode, offset, NO_POOL_ENTRY);
4363   bl(offset);
4364 }
4365 
near_call(HeapObjectRequest request)4366 void Assembler::near_call(HeapObjectRequest request) {
4367   BlockPoolsScope no_pool_before_bl_instr(this);
4368   RequestHeapObject(request);
4369   EmbeddedObjectIndex index = AddEmbeddedObject(Handle<Code>());
4370   RecordRelocInfo(RelocInfo::CODE_TARGET, index, NO_POOL_ENTRY);
4371   DCHECK(is_int32(index));
4372   bl(static_cast<int>(index));
4373 }
4374 
4375 // Constant Pool
4376 
EmitPrologue(Alignment require_alignment)4377 void ConstantPool::EmitPrologue(Alignment require_alignment) {
4378   // Recorded constant pool size is expressed in number of 32-bits words,
4379   // and includes prologue and alignment, but not the jump around the pool
4380   // and the size of the marker itself.
4381   const int marker_size = 1;
4382   int word_count =
4383       ComputeSize(Jump::kOmitted, require_alignment) / kInt32Size - marker_size;
4384   assm_->Emit(LDR_x_lit | Assembler::ImmLLiteral(word_count) |
4385               Assembler::Rt(xzr));
4386   assm_->EmitPoolGuard();
4387 }
4388 
PrologueSize(Jump require_jump) const4389 int ConstantPool::PrologueSize(Jump require_jump) const {
4390   // Prologue is:
4391   //   b   over  ;; if require_jump
4392   //   ldr xzr, #pool_size
4393   //   blr xzr
4394   int prologue_size = require_jump == Jump::kRequired ? kInstrSize : 0;
4395   prologue_size += 2 * kInstrSize;
4396   return prologue_size;
4397 }
4398 
SetLoadOffsetToConstPoolEntry(int load_offset,Instruction * entry_offset,const ConstantPoolKey & key)4399 void ConstantPool::SetLoadOffsetToConstPoolEntry(int load_offset,
4400                                                  Instruction* entry_offset,
4401                                                  const ConstantPoolKey& key) {
4402   Instruction* instr = assm_->InstructionAt(load_offset);
4403   // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0.
4404   DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0);
4405   instr->SetImmPCOffsetTarget(assm_->options(), entry_offset);
4406 }
4407 
Check(Emission force_emit,Jump require_jump,size_t margin)4408 void ConstantPool::Check(Emission force_emit, Jump require_jump,
4409                          size_t margin) {
4410   // Some short sequence of instruction must not be broken up by constant pool
4411   // emission, such sequences are protected by a ConstPool::BlockScope.
4412   if (IsBlocked()) {
4413     // Something is wrong if emission is forced and blocked at the same time.
4414     DCHECK_EQ(force_emit, Emission::kIfNeeded);
4415     return;
4416   }
4417 
4418   // We emit a constant pool only if :
4419   //  * it is not empty
4420   //  * emission is forced by parameter force_emit (e.g. at function end).
4421   //  * emission is mandatory or opportune according to {ShouldEmitNow}.
4422   if (!IsEmpty() && (force_emit == Emission::kForced ||
4423                      ShouldEmitNow(require_jump, margin))) {
4424     // Emit veneers for branches that would go out of range during emission of
4425     // the constant pool.
4426     int worst_case_size = ComputeSize(Jump::kRequired, Alignment::kRequired);
4427     assm_->CheckVeneerPool(false, require_jump == Jump::kRequired,
4428                            assm_->kVeneerDistanceMargin + worst_case_size +
4429                                static_cast<int>(margin));
4430 
4431     // Check that the code buffer is large enough before emitting the constant
4432     // pool (this includes the gap to the relocation information).
4433     int needed_space = worst_case_size + assm_->kGap;
4434     while (assm_->buffer_space() <= needed_space) {
4435       assm_->GrowBuffer();
4436     }
4437 
4438     EmitAndClear(require_jump);
4439   }
4440   // Since a constant pool is (now) empty, move the check offset forward by
4441   // the standard interval.
4442   SetNextCheckIn(ConstantPool::kCheckInterval);
4443 }
4444 
4445 // Pool entries are accessed with pc relative load therefore this cannot be more
4446 // than 1 * MB. Since constant pool emission checks are interval based, and we
4447 // want to keep entries close to the code, we try to emit every 64KB.
4448 const size_t ConstantPool::kMaxDistToPool32 = 1 * MB;
4449 const size_t ConstantPool::kMaxDistToPool64 = 1 * MB;
4450 const size_t ConstantPool::kCheckInterval = 128 * kInstrSize;
4451 const size_t ConstantPool::kApproxDistToPool32 = 64 * KB;
4452 const size_t ConstantPool::kApproxDistToPool64 = kApproxDistToPool32;
4453 
4454 const size_t ConstantPool::kOpportunityDistToPool32 = 64 * KB;
4455 const size_t ConstantPool::kOpportunityDistToPool64 = 64 * KB;
4456 const size_t ConstantPool::kApproxMaxEntryCount = 512;
4457 
ShouldEmitVeneer(int max_reachable_pc,size_t margin)4458 bool Assembler::ShouldEmitVeneer(int max_reachable_pc, size_t margin) {
4459   // Account for the branch around the veneers and the guard.
4460   int protection_offset = 2 * kInstrSize;
4461   return static_cast<intptr_t>(pc_offset() + margin + protection_offset +
4462                                unresolved_branches_.size() *
4463                                    kMaxVeneerCodeSize) >= max_reachable_pc;
4464 }
4465 
RecordVeneerPool(int location_offset,int size)4466 void Assembler::RecordVeneerPool(int location_offset, int size) {
4467   Assembler::BlockPoolsScope block_pools(this, PoolEmissionCheck::kSkip);
4468   RelocInfo rinfo(reinterpret_cast<Address>(buffer_start_) + location_offset,
4469                   RelocInfo::VENEER_POOL, static_cast<intptr_t>(size), Code());
4470   reloc_info_writer.Write(&rinfo);
4471 }
4472 
EmitVeneers(bool force_emit,bool need_protection,size_t margin)4473 void Assembler::EmitVeneers(bool force_emit, bool need_protection,
4474                             size_t margin) {
4475   BlockPoolsScope scope(this, PoolEmissionCheck::kSkip);
4476   RecordComment("[ Veneers");
4477 
4478   // The exact size of the veneer pool must be recorded (see the comment at the
4479   // declaration site of RecordConstPool()), but computing the number of
4480   // veneers that will be generated is not obvious. So instead we remember the
4481   // current position and will record the size after the pool has been
4482   // generated.
4483   Label size_check;
4484   bind(&size_check);
4485   int veneer_pool_relocinfo_loc = pc_offset();
4486 
4487   Label end;
4488   if (need_protection) {
4489     b(&end);
4490   }
4491 
4492   EmitVeneersGuard();
4493 
4494 #ifdef DEBUG
4495   Label veneer_size_check;
4496 #endif
4497 
4498   std::multimap<int, FarBranchInfo>::iterator it, it_to_delete;
4499 
4500   it = unresolved_branches_.begin();
4501   while (it != unresolved_branches_.end()) {
4502     if (force_emit || ShouldEmitVeneer(it->first, margin)) {
4503       Instruction* branch = InstructionAt(it->second.pc_offset_);
4504       Label* label = it->second.label_;
4505 
4506 #ifdef DEBUG
4507       bind(&veneer_size_check);
4508 #endif
4509       // Patch the branch to point to the current position, and emit a branch
4510       // to the label.
4511       Instruction* veneer = reinterpret_cast<Instruction*>(pc_);
4512       RemoveBranchFromLabelLinkChain(branch, label, veneer);
4513       branch->SetImmPCOffsetTarget(options(), veneer);
4514       b(label);
4515 #ifdef DEBUG
4516       DCHECK(SizeOfCodeGeneratedSince(&veneer_size_check) <=
4517              static_cast<uint64_t>(kMaxVeneerCodeSize));
4518       veneer_size_check.Unuse();
4519 #endif
4520 
4521       it_to_delete = it++;
4522       unresolved_branches_.erase(it_to_delete);
4523     } else {
4524       ++it;
4525     }
4526   }
4527 
4528   // Record the veneer pool size.
4529   int pool_size = static_cast<int>(SizeOfCodeGeneratedSince(&size_check));
4530   RecordVeneerPool(veneer_pool_relocinfo_loc, pool_size);
4531 
4532   if (unresolved_branches_.empty()) {
4533     next_veneer_pool_check_ = kMaxInt;
4534   } else {
4535     next_veneer_pool_check_ =
4536         unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
4537   }
4538 
4539   bind(&end);
4540 
4541   RecordComment("]");
4542 }
4543 
CheckVeneerPool(bool force_emit,bool require_jump,size_t margin)4544 void Assembler::CheckVeneerPool(bool force_emit, bool require_jump,
4545                                 size_t margin) {
4546   // There is nothing to do if there are no pending veneer pool entries.
4547   if (unresolved_branches_.empty()) {
4548     DCHECK_EQ(next_veneer_pool_check_, kMaxInt);
4549     return;
4550   }
4551 
4552   DCHECK(pc_offset() < unresolved_branches_first_limit());
4553 
4554   // Some short sequence of instruction mustn't be broken up by veneer pool
4555   // emission, such sequences are protected by calls to BlockVeneerPoolFor and
4556   // BlockVeneerPoolScope.
4557   if (is_veneer_pool_blocked()) {
4558     DCHECK(!force_emit);
4559     return;
4560   }
4561 
4562   if (!require_jump) {
4563     // Prefer emitting veneers protected by an existing instruction.
4564     margin *= kVeneerNoProtectionFactor;
4565   }
4566   if (force_emit || ShouldEmitVeneers(margin)) {
4567     EmitVeneers(force_emit, require_jump, margin);
4568   } else {
4569     next_veneer_pool_check_ =
4570         unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
4571   }
4572 }
4573 
buffer_space() const4574 int Assembler::buffer_space() const {
4575   return static_cast<int>(reloc_info_writer.pos() - pc_);
4576 }
4577 
RecordConstPool(int size)4578 void Assembler::RecordConstPool(int size) {
4579   // We only need this for debugger support, to correctly compute offsets in the
4580   // code.
4581   Assembler::BlockPoolsScope block_pools(this);
4582   RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
4583 }
4584 
PatchAdrFar(int64_t target_offset)4585 void PatchingAssembler::PatchAdrFar(int64_t target_offset) {
4586   // The code at the current instruction should be:
4587   //   adr  rd, 0
4588   //   nop  (adr_far)
4589   //   nop  (adr_far)
4590   //   movz scratch, 0
4591 
4592   // Verify the expected code.
4593   Instruction* expected_adr = InstructionAt(0);
4594   CHECK(expected_adr->IsAdr() && (expected_adr->ImmPCRel() == 0));
4595   int rd_code = expected_adr->Rd();
4596   for (int i = 0; i < kAdrFarPatchableNNops; ++i) {
4597     CHECK(InstructionAt((i + 1) * kInstrSize)->IsNop(ADR_FAR_NOP));
4598   }
4599   Instruction* expected_movz =
4600       InstructionAt((kAdrFarPatchableNInstrs - 1) * kInstrSize);
4601   CHECK(expected_movz->IsMovz() && (expected_movz->ImmMoveWide() == 0) &&
4602         (expected_movz->ShiftMoveWide() == 0));
4603   int scratch_code = expected_movz->Rd();
4604 
4605   // Patch to load the correct address.
4606   Register rd = Register::XRegFromCode(rd_code);
4607   Register scratch = Register::XRegFromCode(scratch_code);
4608   // Addresses are only 48 bits.
4609   adr(rd, target_offset & 0xFFFF);
4610   movz(scratch, (target_offset >> 16) & 0xFFFF, 16);
4611   movk(scratch, (target_offset >> 32) & 0xFFFF, 32);
4612   DCHECK_EQ(target_offset >> 48, 0);
4613   add(rd, rd, scratch);
4614 }
4615 
PatchSubSp(uint32_t immediate)4616 void PatchingAssembler::PatchSubSp(uint32_t immediate) {
4617   // The code at the current instruction should be:
4618   //   sub sp, sp, #0
4619 
4620   // Verify the expected code.
4621   Instruction* expected_adr = InstructionAt(0);
4622   CHECK(expected_adr->IsAddSubImmediate());
4623   sub(sp, sp, immediate);
4624 }
4625 
4626 #undef NEON_3DIFF_LONG_LIST
4627 #undef NEON_3DIFF_HN_LIST
4628 #undef NEON_ACROSSLANES_LIST
4629 #undef NEON_FP2REGMISC_FCVT_LIST
4630 #undef NEON_FP2REGMISC_LIST
4631 #undef NEON_3SAME_LIST
4632 #undef NEON_FP3SAME_LIST_V2
4633 #undef NEON_BYELEMENT_LIST
4634 #undef NEON_FPBYELEMENT_LIST
4635 #undef NEON_BYELEMENT_LONG_LIST
4636 
4637 }  // namespace internal
4638 }  // namespace v8
4639 
4640 #endif  // V8_TARGET_ARCH_ARM64
4641