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