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