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