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