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