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