]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | //===- AArch64Disassembler.cpp - Disassembler for AArch64 -------*- C++ -*-===// |
970d7e83 LB |
2 | // |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
970d7e83 LB |
10 | // |
11 | //===----------------------------------------------------------------------===// | |
12 | ||
1a4d82fc JJ |
13 | #include "AArch64Disassembler.h" |
14 | #include "AArch64ExternalSymbolizer.h" | |
970d7e83 | 15 | #include "AArch64Subtarget.h" |
1a4d82fc | 16 | #include "MCTargetDesc/AArch64AddressingModes.h" |
970d7e83 | 17 | #include "Utils/AArch64BaseInfo.h" |
970d7e83 | 18 | #include "llvm/MC/MCFixedLenDisassembler.h" |
1a4d82fc | 19 | #include "llvm/MC/MCInst.h" |
970d7e83 | 20 | #include "llvm/Support/Debug.h" |
970d7e83 LB |
21 | #include "llvm/Support/ErrorHandling.h" |
22 | #include "llvm/Support/TargetRegistry.h" | |
970d7e83 LB |
23 | |
24 | using namespace llvm; | |
25 | ||
1a4d82fc | 26 | #define DEBUG_TYPE "aarch64-disassembler" |
970d7e83 | 27 | |
1a4d82fc JJ |
28 | // Pull DecodeStatus and its enum values into the global namespace. |
29 | typedef llvm::MCDisassembler::DecodeStatus DecodeStatus; | |
970d7e83 | 30 | |
1a4d82fc JJ |
31 | // Forward declare these because the autogenerated code will reference them. |
32 | // Definitions are further down. | |
970d7e83 LB |
33 | static DecodeStatus DecodeFPR128RegisterClass(llvm::MCInst &Inst, |
34 | unsigned RegNo, uint64_t Address, | |
35 | const void *Decoder); | |
1a4d82fc JJ |
36 | static DecodeStatus DecodeFPR128_loRegisterClass(llvm::MCInst &Inst, |
37 | unsigned RegNo, | |
38 | uint64_t Address, | |
39 | const void *Decoder); | |
40 | static DecodeStatus DecodeFPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo, | |
41 | uint64_t Address, | |
42 | const void *Decoder); | |
43 | static DecodeStatus DecodeFPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo, | |
44 | uint64_t Address, | |
45 | const void *Decoder); | |
46 | static DecodeStatus DecodeFPR16RegisterClass(llvm::MCInst &Inst, unsigned RegNo, | |
47 | uint64_t Address, | |
48 | const void *Decoder); | |
49 | static DecodeStatus DecodeFPR8RegisterClass(llvm::MCInst &Inst, unsigned RegNo, | |
50 | uint64_t Address, | |
51 | const void *Decoder); | |
52 | static DecodeStatus DecodeGPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo, | |
53 | uint64_t Address, | |
54 | const void *Decoder); | |
55 | static DecodeStatus DecodeGPR64spRegisterClass(llvm::MCInst &Inst, | |
56 | unsigned RegNo, uint64_t Address, | |
970d7e83 | 57 | const void *Decoder); |
1a4d82fc | 58 | static DecodeStatus DecodeGPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo, |
970d7e83 LB |
59 | uint64_t Address, |
60 | const void *Decoder); | |
1a4d82fc JJ |
61 | static DecodeStatus DecodeGPR32spRegisterClass(llvm::MCInst &Inst, |
62 | unsigned RegNo, uint64_t Address, | |
63 | const void *Decoder); | |
64 | static DecodeStatus DecodeQQRegisterClass(llvm::MCInst &Inst, unsigned RegNo, | |
65 | uint64_t Address, | |
66 | const void *Decoder); | |
67 | static DecodeStatus DecodeQQQRegisterClass(llvm::MCInst &Inst, unsigned RegNo, | |
68 | uint64_t Address, | |
69 | const void *Decoder); | |
70 | static DecodeStatus DecodeQQQQRegisterClass(llvm::MCInst &Inst, unsigned RegNo, | |
970d7e83 LB |
71 | uint64_t Address, |
72 | const void *Decoder); | |
1a4d82fc JJ |
73 | static DecodeStatus DecodeDDRegisterClass(llvm::MCInst &Inst, unsigned RegNo, |
74 | uint64_t Address, | |
75 | const void *Decoder); | |
76 | static DecodeStatus DecodeDDDRegisterClass(llvm::MCInst &Inst, unsigned RegNo, | |
970d7e83 LB |
77 | uint64_t Address, |
78 | const void *Decoder); | |
1a4d82fc | 79 | static DecodeStatus DecodeDDDDRegisterClass(llvm::MCInst &Inst, unsigned RegNo, |
970d7e83 LB |
80 | uint64_t Address, |
81 | const void *Decoder); | |
1a4d82fc JJ |
82 | |
83 | static DecodeStatus DecodeFixedPointScaleImm32(llvm::MCInst &Inst, unsigned Imm, | |
84 | uint64_t Address, | |
85 | const void *Decoder); | |
86 | static DecodeStatus DecodeFixedPointScaleImm64(llvm::MCInst &Inst, unsigned Imm, | |
87 | uint64_t Address, | |
88 | const void *Decoder); | |
89 | static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm, | |
90 | uint64_t Address, const void *Decoder); | |
91 | static DecodeStatus DecodeMemExtend(llvm::MCInst &Inst, unsigned Imm, | |
92 | uint64_t Address, const void *Decoder); | |
93 | static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, | |
94 | uint64_t Address, const void *Decoder); | |
95 | static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm, | |
96 | uint64_t Address, const void *Decoder); | |
97 | static DecodeStatus DecodeThreeAddrSRegInstruction(llvm::MCInst &Inst, | |
98 | uint32_t insn, | |
99 | uint64_t Address, | |
100 | const void *Decoder); | |
101 | static DecodeStatus DecodeMoveImmInstruction(llvm::MCInst &Inst, uint32_t insn, | |
102 | uint64_t Address, | |
103 | const void *Decoder); | |
104 | static DecodeStatus DecodeUnsignedLdStInstruction(llvm::MCInst &Inst, | |
105 | uint32_t insn, | |
106 | uint64_t Address, | |
107 | const void *Decoder); | |
108 | static DecodeStatus DecodeSignedLdStInstruction(llvm::MCInst &Inst, | |
109 | uint32_t insn, uint64_t Address, | |
110 | const void *Decoder); | |
111 | static DecodeStatus DecodeExclusiveLdStInstruction(llvm::MCInst &Inst, | |
112 | uint32_t insn, | |
113 | uint64_t Address, | |
114 | const void *Decoder); | |
115 | static DecodeStatus DecodePairLdStInstruction(llvm::MCInst &Inst, uint32_t insn, | |
970d7e83 LB |
116 | uint64_t Address, |
117 | const void *Decoder); | |
1a4d82fc JJ |
118 | static DecodeStatus DecodeAddSubERegInstruction(llvm::MCInst &Inst, |
119 | uint32_t insn, uint64_t Address, | |
120 | const void *Decoder); | |
121 | static DecodeStatus DecodeLogicalImmInstruction(llvm::MCInst &Inst, | |
122 | uint32_t insn, uint64_t Address, | |
123 | const void *Decoder); | |
124 | static DecodeStatus DecodeModImmInstruction(llvm::MCInst &Inst, uint32_t insn, | |
125 | uint64_t Address, | |
126 | const void *Decoder); | |
127 | static DecodeStatus DecodeModImmTiedInstruction(llvm::MCInst &Inst, | |
128 | uint32_t insn, uint64_t Address, | |
129 | const void *Decoder); | |
130 | static DecodeStatus DecodeAdrInstruction(llvm::MCInst &Inst, uint32_t insn, | |
131 | uint64_t Address, const void *Decoder); | |
132 | static DecodeStatus DecodeBaseAddSubImm(llvm::MCInst &Inst, uint32_t insn, | |
133 | uint64_t Address, const void *Decoder); | |
134 | static DecodeStatus DecodeUnconditionalBranch(llvm::MCInst &Inst, uint32_t insn, | |
970d7e83 LB |
135 | uint64_t Address, |
136 | const void *Decoder); | |
1a4d82fc JJ |
137 | static DecodeStatus DecodeSystemPStateInstruction(llvm::MCInst &Inst, |
138 | uint32_t insn, | |
139 | uint64_t Address, | |
140 | const void *Decoder); | |
141 | static DecodeStatus DecodeTestAndBranch(llvm::MCInst &Inst, uint32_t insn, | |
142 | uint64_t Address, const void *Decoder); | |
970d7e83 | 143 | |
1a4d82fc | 144 | static DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn, |
970d7e83 LB |
145 | uint64_t Address, |
146 | const void *Decoder); | |
1a4d82fc JJ |
147 | static DecodeStatus DecodeVecShiftR64Imm(llvm::MCInst &Inst, unsigned Imm, |
148 | uint64_t Addr, const void *Decoder); | |
149 | static DecodeStatus DecodeVecShiftR64ImmNarrow(llvm::MCInst &Inst, unsigned Imm, | |
150 | uint64_t Addr, | |
151 | const void *Decoder); | |
152 | static DecodeStatus DecodeVecShiftR32Imm(llvm::MCInst &Inst, unsigned Imm, | |
153 | uint64_t Addr, const void *Decoder); | |
154 | static DecodeStatus DecodeVecShiftR32ImmNarrow(llvm::MCInst &Inst, unsigned Imm, | |
155 | uint64_t Addr, | |
156 | const void *Decoder); | |
157 | static DecodeStatus DecodeVecShiftR16Imm(llvm::MCInst &Inst, unsigned Imm, | |
158 | uint64_t Addr, const void *Decoder); | |
159 | static DecodeStatus DecodeVecShiftR16ImmNarrow(llvm::MCInst &Inst, unsigned Imm, | |
160 | uint64_t Addr, | |
161 | const void *Decoder); | |
162 | static DecodeStatus DecodeVecShiftR8Imm(llvm::MCInst &Inst, unsigned Imm, | |
163 | uint64_t Addr, const void *Decoder); | |
164 | static DecodeStatus DecodeVecShiftL64Imm(llvm::MCInst &Inst, unsigned Imm, | |
165 | uint64_t Addr, const void *Decoder); | |
166 | static DecodeStatus DecodeVecShiftL32Imm(llvm::MCInst &Inst, unsigned Imm, | |
167 | uint64_t Addr, const void *Decoder); | |
168 | static DecodeStatus DecodeVecShiftL16Imm(llvm::MCInst &Inst, unsigned Imm, | |
169 | uint64_t Addr, const void *Decoder); | |
170 | static DecodeStatus DecodeVecShiftL8Imm(llvm::MCInst &Inst, unsigned Imm, | |
171 | uint64_t Addr, const void *Decoder); | |
970d7e83 LB |
172 | |
173 | static bool Check(DecodeStatus &Out, DecodeStatus In) { | |
174 | switch (In) { | |
175 | case MCDisassembler::Success: | |
176 | // Out stays the same. | |
177 | return true; | |
178 | case MCDisassembler::SoftFail: | |
179 | Out = In; | |
180 | return true; | |
181 | case MCDisassembler::Fail: | |
182 | Out = In; | |
183 | return false; | |
184 | } | |
185 | llvm_unreachable("Invalid DecodeStatus!"); | |
186 | } | |
187 | ||
1a4d82fc JJ |
188 | #include "AArch64GenDisassemblerTables.inc" |
189 | #include "AArch64GenInstrInfo.inc" | |
190 | ||
191 | #define Success llvm::MCDisassembler::Success | |
192 | #define Fail llvm::MCDisassembler::Fail | |
193 | #define SoftFail llvm::MCDisassembler::SoftFail | |
194 | ||
195 | static MCDisassembler *createAArch64Disassembler(const Target &T, | |
196 | const MCSubtargetInfo &STI, | |
197 | MCContext &Ctx) { | |
198 | return new AArch64Disassembler(STI, Ctx); | |
199 | } | |
200 | ||
970d7e83 | 201 | DecodeStatus AArch64Disassembler::getInstruction(MCInst &MI, uint64_t &Size, |
85aaf69f SL |
202 | ArrayRef<uint8_t> Bytes, |
203 | uint64_t Address, | |
204 | raw_ostream &OS, | |
205 | raw_ostream &CS) const { | |
206 | CommentStream = &CS; | |
970d7e83 | 207 | |
1a4d82fc | 208 | Size = 0; |
970d7e83 | 209 | // We want to read exactly 4 bytes of data. |
85aaf69f | 210 | if (Bytes.size() < 4) |
1a4d82fc JJ |
211 | return Fail; |
212 | Size = 4; | |
970d7e83 LB |
213 | |
214 | // Encoded as a small-endian 32-bit word in the stream. | |
85aaf69f SL |
215 | uint32_t Insn = |
216 | (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0); | |
970d7e83 LB |
217 | |
218 | // Calling the auto-generated decoder function. | |
85aaf69f | 219 | return decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI); |
1a4d82fc | 220 | } |
970d7e83 | 221 | |
1a4d82fc JJ |
222 | static MCSymbolizer * |
223 | createAArch64ExternalSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, | |
224 | LLVMSymbolLookupCallback SymbolLookUp, | |
225 | void *DisInfo, MCContext *Ctx, | |
226 | MCRelocationInfo *RelInfo) { | |
227 | return new llvm::AArch64ExternalSymbolizer( | |
228 | *Ctx, | |
229 | std::unique_ptr<MCRelocationInfo>(RelInfo), | |
230 | GetOpInfo, SymbolLookUp, DisInfo); | |
970d7e83 LB |
231 | } |
232 | ||
1a4d82fc JJ |
233 | extern "C" void LLVMInitializeAArch64Disassembler() { |
234 | TargetRegistry::RegisterMCDisassembler(TheAArch64leTarget, | |
235 | createAArch64Disassembler); | |
236 | TargetRegistry::RegisterMCDisassembler(TheAArch64beTarget, | |
237 | createAArch64Disassembler); | |
238 | TargetRegistry::RegisterMCSymbolizer(TheAArch64leTarget, | |
239 | createAArch64ExternalSymbolizer); | |
240 | TargetRegistry::RegisterMCSymbolizer(TheAArch64beTarget, | |
241 | createAArch64ExternalSymbolizer); | |
242 | ||
243 | TargetRegistry::RegisterMCDisassembler(TheARM64Target, | |
244 | createAArch64Disassembler); | |
245 | TargetRegistry::RegisterMCSymbolizer(TheARM64Target, | |
246 | createAArch64ExternalSymbolizer); | |
970d7e83 LB |
247 | } |
248 | ||
1a4d82fc JJ |
249 | static const unsigned FPR128DecoderTable[] = { |
250 | AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4, | |
251 | AArch64::Q5, AArch64::Q6, AArch64::Q7, AArch64::Q8, AArch64::Q9, | |
252 | AArch64::Q10, AArch64::Q11, AArch64::Q12, AArch64::Q13, AArch64::Q14, | |
253 | AArch64::Q15, AArch64::Q16, AArch64::Q17, AArch64::Q18, AArch64::Q19, | |
254 | AArch64::Q20, AArch64::Q21, AArch64::Q22, AArch64::Q23, AArch64::Q24, | |
255 | AArch64::Q25, AArch64::Q26, AArch64::Q27, AArch64::Q28, AArch64::Q29, | |
256 | AArch64::Q30, AArch64::Q31 | |
257 | }; | |
258 | ||
259 | static DecodeStatus DecodeFPR128RegisterClass(MCInst &Inst, unsigned RegNo, | |
260 | uint64_t Addr, | |
261 | const void *Decoder) { | |
970d7e83 | 262 | if (RegNo > 31) |
1a4d82fc | 263 | return Fail; |
970d7e83 | 264 | |
1a4d82fc | 265 | unsigned Register = FPR128DecoderTable[RegNo]; |
970d7e83 | 266 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc JJ |
267 | return Success; |
268 | } | |
269 | ||
270 | static DecodeStatus DecodeFPR128_loRegisterClass(MCInst &Inst, unsigned RegNo, | |
271 | uint64_t Addr, | |
272 | const void *Decoder) { | |
273 | if (RegNo > 15) | |
274 | return Fail; | |
275 | return DecodeFPR128RegisterClass(Inst, RegNo, Addr, Decoder); | |
970d7e83 LB |
276 | } |
277 | ||
1a4d82fc JJ |
278 | static const unsigned FPR64DecoderTable[] = { |
279 | AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4, | |
280 | AArch64::D5, AArch64::D6, AArch64::D7, AArch64::D8, AArch64::D9, | |
281 | AArch64::D10, AArch64::D11, AArch64::D12, AArch64::D13, AArch64::D14, | |
282 | AArch64::D15, AArch64::D16, AArch64::D17, AArch64::D18, AArch64::D19, | |
283 | AArch64::D20, AArch64::D21, AArch64::D22, AArch64::D23, AArch64::D24, | |
284 | AArch64::D25, AArch64::D26, AArch64::D27, AArch64::D28, AArch64::D29, | |
285 | AArch64::D30, AArch64::D31 | |
286 | }; | |
287 | ||
288 | static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, unsigned RegNo, | |
289 | uint64_t Addr, | |
290 | const void *Decoder) { | |
970d7e83 | 291 | if (RegNo > 31) |
1a4d82fc | 292 | return Fail; |
970d7e83 | 293 | |
1a4d82fc | 294 | unsigned Register = FPR64DecoderTable[RegNo]; |
970d7e83 | 295 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc | 296 | return Success; |
970d7e83 LB |
297 | } |
298 | ||
1a4d82fc JJ |
299 | static const unsigned FPR32DecoderTable[] = { |
300 | AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4, | |
301 | AArch64::S5, AArch64::S6, AArch64::S7, AArch64::S8, AArch64::S9, | |
302 | AArch64::S10, AArch64::S11, AArch64::S12, AArch64::S13, AArch64::S14, | |
303 | AArch64::S15, AArch64::S16, AArch64::S17, AArch64::S18, AArch64::S19, | |
304 | AArch64::S20, AArch64::S21, AArch64::S22, AArch64::S23, AArch64::S24, | |
305 | AArch64::S25, AArch64::S26, AArch64::S27, AArch64::S28, AArch64::S29, | |
306 | AArch64::S30, AArch64::S31 | |
307 | }; | |
308 | ||
309 | static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, unsigned RegNo, | |
310 | uint64_t Addr, | |
970d7e83 LB |
311 | const void *Decoder) { |
312 | if (RegNo > 31) | |
1a4d82fc | 313 | return Fail; |
970d7e83 | 314 | |
1a4d82fc | 315 | unsigned Register = FPR32DecoderTable[RegNo]; |
970d7e83 | 316 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc | 317 | return Success; |
970d7e83 LB |
318 | } |
319 | ||
1a4d82fc JJ |
320 | static const unsigned FPR16DecoderTable[] = { |
321 | AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4, | |
322 | AArch64::H5, AArch64::H6, AArch64::H7, AArch64::H8, AArch64::H9, | |
323 | AArch64::H10, AArch64::H11, AArch64::H12, AArch64::H13, AArch64::H14, | |
324 | AArch64::H15, AArch64::H16, AArch64::H17, AArch64::H18, AArch64::H19, | |
325 | AArch64::H20, AArch64::H21, AArch64::H22, AArch64::H23, AArch64::H24, | |
326 | AArch64::H25, AArch64::H26, AArch64::H27, AArch64::H28, AArch64::H29, | |
327 | AArch64::H30, AArch64::H31 | |
328 | }; | |
329 | ||
330 | static DecodeStatus DecodeFPR16RegisterClass(MCInst &Inst, unsigned RegNo, | |
331 | uint64_t Addr, | |
332 | const void *Decoder) { | |
970d7e83 | 333 | if (RegNo > 31) |
1a4d82fc | 334 | return Fail; |
970d7e83 | 335 | |
1a4d82fc | 336 | unsigned Register = FPR16DecoderTable[RegNo]; |
970d7e83 | 337 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc | 338 | return Success; |
970d7e83 LB |
339 | } |
340 | ||
1a4d82fc JJ |
341 | static const unsigned FPR8DecoderTable[] = { |
342 | AArch64::B0, AArch64::B1, AArch64::B2, AArch64::B3, AArch64::B4, | |
343 | AArch64::B5, AArch64::B6, AArch64::B7, AArch64::B8, AArch64::B9, | |
344 | AArch64::B10, AArch64::B11, AArch64::B12, AArch64::B13, AArch64::B14, | |
345 | AArch64::B15, AArch64::B16, AArch64::B17, AArch64::B18, AArch64::B19, | |
346 | AArch64::B20, AArch64::B21, AArch64::B22, AArch64::B23, AArch64::B24, | |
347 | AArch64::B25, AArch64::B26, AArch64::B27, AArch64::B28, AArch64::B29, | |
348 | AArch64::B30, AArch64::B31 | |
349 | }; | |
350 | ||
351 | static DecodeStatus DecodeFPR8RegisterClass(MCInst &Inst, unsigned RegNo, | |
352 | uint64_t Addr, | |
353 | const void *Decoder) { | |
970d7e83 | 354 | if (RegNo > 31) |
1a4d82fc | 355 | return Fail; |
970d7e83 | 356 | |
1a4d82fc | 357 | unsigned Register = FPR8DecoderTable[RegNo]; |
970d7e83 | 358 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc | 359 | return Success; |
970d7e83 LB |
360 | } |
361 | ||
1a4d82fc JJ |
362 | static const unsigned GPR64DecoderTable[] = { |
363 | AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4, | |
364 | AArch64::X5, AArch64::X6, AArch64::X7, AArch64::X8, AArch64::X9, | |
365 | AArch64::X10, AArch64::X11, AArch64::X12, AArch64::X13, AArch64::X14, | |
366 | AArch64::X15, AArch64::X16, AArch64::X17, AArch64::X18, AArch64::X19, | |
367 | AArch64::X20, AArch64::X21, AArch64::X22, AArch64::X23, AArch64::X24, | |
368 | AArch64::X25, AArch64::X26, AArch64::X27, AArch64::X28, AArch64::FP, | |
369 | AArch64::LR, AArch64::XZR | |
370 | }; | |
371 | ||
372 | static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, unsigned RegNo, | |
373 | uint64_t Addr, | |
374 | const void *Decoder) { | |
970d7e83 | 375 | if (RegNo > 31) |
1a4d82fc | 376 | return Fail; |
970d7e83 | 377 | |
1a4d82fc | 378 | unsigned Register = GPR64DecoderTable[RegNo]; |
970d7e83 | 379 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc | 380 | return Success; |
970d7e83 LB |
381 | } |
382 | ||
1a4d82fc JJ |
383 | static DecodeStatus DecodeGPR64spRegisterClass(MCInst &Inst, unsigned RegNo, |
384 | uint64_t Addr, | |
385 | const void *Decoder) { | |
386 | if (RegNo > 31) | |
387 | return Fail; | |
388 | unsigned Register = GPR64DecoderTable[RegNo]; | |
389 | if (Register == AArch64::XZR) | |
390 | Register = AArch64::SP; | |
391 | Inst.addOperand(MCOperand::CreateReg(Register)); | |
392 | return Success; | |
393 | } | |
394 | ||
395 | static const unsigned GPR32DecoderTable[] = { | |
396 | AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4, | |
397 | AArch64::W5, AArch64::W6, AArch64::W7, AArch64::W8, AArch64::W9, | |
398 | AArch64::W10, AArch64::W11, AArch64::W12, AArch64::W13, AArch64::W14, | |
399 | AArch64::W15, AArch64::W16, AArch64::W17, AArch64::W18, AArch64::W19, | |
400 | AArch64::W20, AArch64::W21, AArch64::W22, AArch64::W23, AArch64::W24, | |
401 | AArch64::W25, AArch64::W26, AArch64::W27, AArch64::W28, AArch64::W29, | |
402 | AArch64::W30, AArch64::WZR | |
403 | }; | |
970d7e83 | 404 | |
1a4d82fc JJ |
405 | static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, |
406 | uint64_t Addr, | |
407 | const void *Decoder) { | |
970d7e83 | 408 | if (RegNo > 31) |
1a4d82fc | 409 | return Fail; |
970d7e83 | 410 | |
1a4d82fc | 411 | unsigned Register = GPR32DecoderTable[RegNo]; |
970d7e83 | 412 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc | 413 | return Success; |
970d7e83 LB |
414 | } |
415 | ||
1a4d82fc JJ |
416 | static DecodeStatus DecodeGPR32spRegisterClass(MCInst &Inst, unsigned RegNo, |
417 | uint64_t Addr, | |
418 | const void *Decoder) { | |
970d7e83 | 419 | if (RegNo > 31) |
1a4d82fc | 420 | return Fail; |
970d7e83 | 421 | |
1a4d82fc JJ |
422 | unsigned Register = GPR32DecoderTable[RegNo]; |
423 | if (Register == AArch64::WZR) | |
424 | Register = AArch64::WSP; | |
970d7e83 | 425 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc | 426 | return Success; |
970d7e83 LB |
427 | } |
428 | ||
1a4d82fc JJ |
429 | static const unsigned VectorDecoderTable[] = { |
430 | AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4, | |
431 | AArch64::Q5, AArch64::Q6, AArch64::Q7, AArch64::Q8, AArch64::Q9, | |
432 | AArch64::Q10, AArch64::Q11, AArch64::Q12, AArch64::Q13, AArch64::Q14, | |
433 | AArch64::Q15, AArch64::Q16, AArch64::Q17, AArch64::Q18, AArch64::Q19, | |
434 | AArch64::Q20, AArch64::Q21, AArch64::Q22, AArch64::Q23, AArch64::Q24, | |
435 | AArch64::Q25, AArch64::Q26, AArch64::Q27, AArch64::Q28, AArch64::Q29, | |
436 | AArch64::Q30, AArch64::Q31 | |
437 | }; | |
970d7e83 | 438 | |
1a4d82fc JJ |
439 | static DecodeStatus DecodeVectorRegisterClass(MCInst &Inst, unsigned RegNo, |
440 | uint64_t Addr, | |
441 | const void *Decoder) { | |
970d7e83 | 442 | if (RegNo > 31) |
1a4d82fc | 443 | return Fail; |
970d7e83 | 444 | |
1a4d82fc | 445 | unsigned Register = VectorDecoderTable[RegNo]; |
970d7e83 | 446 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc | 447 | return Success; |
970d7e83 LB |
448 | } |
449 | ||
1a4d82fc JJ |
450 | static const unsigned QQDecoderTable[] = { |
451 | AArch64::Q0_Q1, AArch64::Q1_Q2, AArch64::Q2_Q3, AArch64::Q3_Q4, | |
452 | AArch64::Q4_Q5, AArch64::Q5_Q6, AArch64::Q6_Q7, AArch64::Q7_Q8, | |
453 | AArch64::Q8_Q9, AArch64::Q9_Q10, AArch64::Q10_Q11, AArch64::Q11_Q12, | |
454 | AArch64::Q12_Q13, AArch64::Q13_Q14, AArch64::Q14_Q15, AArch64::Q15_Q16, | |
455 | AArch64::Q16_Q17, AArch64::Q17_Q18, AArch64::Q18_Q19, AArch64::Q19_Q20, | |
456 | AArch64::Q20_Q21, AArch64::Q21_Q22, AArch64::Q22_Q23, AArch64::Q23_Q24, | |
457 | AArch64::Q24_Q25, AArch64::Q25_Q26, AArch64::Q26_Q27, AArch64::Q27_Q28, | |
458 | AArch64::Q28_Q29, AArch64::Q29_Q30, AArch64::Q30_Q31, AArch64::Q31_Q0 | |
459 | }; | |
970d7e83 | 460 | |
1a4d82fc JJ |
461 | static DecodeStatus DecodeQQRegisterClass(MCInst &Inst, unsigned RegNo, |
462 | uint64_t Addr, const void *Decoder) { | |
463 | if (RegNo > 31) | |
464 | return Fail; | |
465 | unsigned Register = QQDecoderTable[RegNo]; | |
970d7e83 | 466 | Inst.addOperand(MCOperand::CreateReg(Register)); |
1a4d82fc | 467 | return Success; |
970d7e83 LB |
468 | } |
469 | ||
1a4d82fc JJ |
470 | static const unsigned QQQDecoderTable[] = { |
471 | AArch64::Q0_Q1_Q2, AArch64::Q1_Q2_Q3, AArch64::Q2_Q3_Q4, | |
472 | AArch64::Q3_Q4_Q5, AArch64::Q4_Q5_Q6, AArch64::Q5_Q6_Q7, | |
473 | AArch64::Q6_Q7_Q8, AArch64::Q7_Q8_Q9, AArch64::Q8_Q9_Q10, | |
474 | AArch64::Q9_Q10_Q11, AArch64::Q10_Q11_Q12, AArch64::Q11_Q12_Q13, | |
475 | AArch64::Q12_Q13_Q14, AArch64::Q13_Q14_Q15, AArch64::Q14_Q15_Q16, | |
476 | AArch64::Q15_Q16_Q17, AArch64::Q16_Q17_Q18, AArch64::Q17_Q18_Q19, | |
477 | AArch64::Q18_Q19_Q20, AArch64::Q19_Q20_Q21, AArch64::Q20_Q21_Q22, | |
478 | AArch64::Q21_Q22_Q23, AArch64::Q22_Q23_Q24, AArch64::Q23_Q24_Q25, | |
479 | AArch64::Q24_Q25_Q26, AArch64::Q25_Q26_Q27, AArch64::Q26_Q27_Q28, | |
480 | AArch64::Q27_Q28_Q29, AArch64::Q28_Q29_Q30, AArch64::Q29_Q30_Q31, | |
481 | AArch64::Q30_Q31_Q0, AArch64::Q31_Q0_Q1 | |
482 | }; | |
970d7e83 | 483 | |
1a4d82fc JJ |
484 | static DecodeStatus DecodeQQQRegisterClass(MCInst &Inst, unsigned RegNo, |
485 | uint64_t Addr, const void *Decoder) { | |
486 | if (RegNo > 31) | |
487 | return Fail; | |
488 | unsigned Register = QQQDecoderTable[RegNo]; | |
489 | Inst.addOperand(MCOperand::CreateReg(Register)); | |
490 | return Success; | |
970d7e83 LB |
491 | } |
492 | ||
1a4d82fc JJ |
493 | static const unsigned QQQQDecoderTable[] = { |
494 | AArch64::Q0_Q1_Q2_Q3, AArch64::Q1_Q2_Q3_Q4, AArch64::Q2_Q3_Q4_Q5, | |
495 | AArch64::Q3_Q4_Q5_Q6, AArch64::Q4_Q5_Q6_Q7, AArch64::Q5_Q6_Q7_Q8, | |
496 | AArch64::Q6_Q7_Q8_Q9, AArch64::Q7_Q8_Q9_Q10, AArch64::Q8_Q9_Q10_Q11, | |
497 | AArch64::Q9_Q10_Q11_Q12, AArch64::Q10_Q11_Q12_Q13, AArch64::Q11_Q12_Q13_Q14, | |
498 | AArch64::Q12_Q13_Q14_Q15, AArch64::Q13_Q14_Q15_Q16, AArch64::Q14_Q15_Q16_Q17, | |
499 | AArch64::Q15_Q16_Q17_Q18, AArch64::Q16_Q17_Q18_Q19, AArch64::Q17_Q18_Q19_Q20, | |
500 | AArch64::Q18_Q19_Q20_Q21, AArch64::Q19_Q20_Q21_Q22, AArch64::Q20_Q21_Q22_Q23, | |
501 | AArch64::Q21_Q22_Q23_Q24, AArch64::Q22_Q23_Q24_Q25, AArch64::Q23_Q24_Q25_Q26, | |
502 | AArch64::Q24_Q25_Q26_Q27, AArch64::Q25_Q26_Q27_Q28, AArch64::Q26_Q27_Q28_Q29, | |
503 | AArch64::Q27_Q28_Q29_Q30, AArch64::Q28_Q29_Q30_Q31, AArch64::Q29_Q30_Q31_Q0, | |
504 | AArch64::Q30_Q31_Q0_Q1, AArch64::Q31_Q0_Q1_Q2 | |
505 | }; | |
970d7e83 | 506 | |
1a4d82fc JJ |
507 | static DecodeStatus DecodeQQQQRegisterClass(MCInst &Inst, unsigned RegNo, |
508 | uint64_t Addr, | |
509 | const void *Decoder) { | |
510 | if (RegNo > 31) | |
511 | return Fail; | |
512 | unsigned Register = QQQQDecoderTable[RegNo]; | |
513 | Inst.addOperand(MCOperand::CreateReg(Register)); | |
514 | return Success; | |
970d7e83 LB |
515 | } |
516 | ||
1a4d82fc JJ |
517 | static const unsigned DDDecoderTable[] = { |
518 | AArch64::D0_D1, AArch64::D1_D2, AArch64::D2_D3, AArch64::D3_D4, | |
519 | AArch64::D4_D5, AArch64::D5_D6, AArch64::D6_D7, AArch64::D7_D8, | |
520 | AArch64::D8_D9, AArch64::D9_D10, AArch64::D10_D11, AArch64::D11_D12, | |
521 | AArch64::D12_D13, AArch64::D13_D14, AArch64::D14_D15, AArch64::D15_D16, | |
522 | AArch64::D16_D17, AArch64::D17_D18, AArch64::D18_D19, AArch64::D19_D20, | |
523 | AArch64::D20_D21, AArch64::D21_D22, AArch64::D22_D23, AArch64::D23_D24, | |
524 | AArch64::D24_D25, AArch64::D25_D26, AArch64::D26_D27, AArch64::D27_D28, | |
525 | AArch64::D28_D29, AArch64::D29_D30, AArch64::D30_D31, AArch64::D31_D0 | |
526 | }; | |
970d7e83 | 527 | |
1a4d82fc JJ |
528 | static DecodeStatus DecodeDDRegisterClass(MCInst &Inst, unsigned RegNo, |
529 | uint64_t Addr, const void *Decoder) { | |
530 | if (RegNo > 31) | |
531 | return Fail; | |
532 | unsigned Register = DDDecoderTable[RegNo]; | |
533 | Inst.addOperand(MCOperand::CreateReg(Register)); | |
534 | return Success; | |
970d7e83 LB |
535 | } |
536 | ||
1a4d82fc JJ |
537 | static const unsigned DDDDecoderTable[] = { |
538 | AArch64::D0_D1_D2, AArch64::D1_D2_D3, AArch64::D2_D3_D4, | |
539 | AArch64::D3_D4_D5, AArch64::D4_D5_D6, AArch64::D5_D6_D7, | |
540 | AArch64::D6_D7_D8, AArch64::D7_D8_D9, AArch64::D8_D9_D10, | |
541 | AArch64::D9_D10_D11, AArch64::D10_D11_D12, AArch64::D11_D12_D13, | |
542 | AArch64::D12_D13_D14, AArch64::D13_D14_D15, AArch64::D14_D15_D16, | |
543 | AArch64::D15_D16_D17, AArch64::D16_D17_D18, AArch64::D17_D18_D19, | |
544 | AArch64::D18_D19_D20, AArch64::D19_D20_D21, AArch64::D20_D21_D22, | |
545 | AArch64::D21_D22_D23, AArch64::D22_D23_D24, AArch64::D23_D24_D25, | |
546 | AArch64::D24_D25_D26, AArch64::D25_D26_D27, AArch64::D26_D27_D28, | |
547 | AArch64::D27_D28_D29, AArch64::D28_D29_D30, AArch64::D29_D30_D31, | |
548 | AArch64::D30_D31_D0, AArch64::D31_D0_D1 | |
549 | }; | |
970d7e83 | 550 | |
1a4d82fc JJ |
551 | static DecodeStatus DecodeDDDRegisterClass(MCInst &Inst, unsigned RegNo, |
552 | uint64_t Addr, const void *Decoder) { | |
553 | if (RegNo > 31) | |
554 | return Fail; | |
555 | unsigned Register = DDDDecoderTable[RegNo]; | |
556 | Inst.addOperand(MCOperand::CreateReg(Register)); | |
557 | return Success; | |
558 | } | |
970d7e83 | 559 | |
1a4d82fc JJ |
560 | static const unsigned DDDDDecoderTable[] = { |
561 | AArch64::D0_D1_D2_D3, AArch64::D1_D2_D3_D4, AArch64::D2_D3_D4_D5, | |
562 | AArch64::D3_D4_D5_D6, AArch64::D4_D5_D6_D7, AArch64::D5_D6_D7_D8, | |
563 | AArch64::D6_D7_D8_D9, AArch64::D7_D8_D9_D10, AArch64::D8_D9_D10_D11, | |
564 | AArch64::D9_D10_D11_D12, AArch64::D10_D11_D12_D13, AArch64::D11_D12_D13_D14, | |
565 | AArch64::D12_D13_D14_D15, AArch64::D13_D14_D15_D16, AArch64::D14_D15_D16_D17, | |
566 | AArch64::D15_D16_D17_D18, AArch64::D16_D17_D18_D19, AArch64::D17_D18_D19_D20, | |
567 | AArch64::D18_D19_D20_D21, AArch64::D19_D20_D21_D22, AArch64::D20_D21_D22_D23, | |
568 | AArch64::D21_D22_D23_D24, AArch64::D22_D23_D24_D25, AArch64::D23_D24_D25_D26, | |
569 | AArch64::D24_D25_D26_D27, AArch64::D25_D26_D27_D28, AArch64::D26_D27_D28_D29, | |
570 | AArch64::D27_D28_D29_D30, AArch64::D28_D29_D30_D31, AArch64::D29_D30_D31_D0, | |
571 | AArch64::D30_D31_D0_D1, AArch64::D31_D0_D1_D2 | |
572 | }; | |
970d7e83 | 573 | |
1a4d82fc JJ |
574 | static DecodeStatus DecodeDDDDRegisterClass(MCInst &Inst, unsigned RegNo, |
575 | uint64_t Addr, | |
576 | const void *Decoder) { | |
577 | if (RegNo > 31) | |
578 | return Fail; | |
579 | unsigned Register = DDDDDecoderTable[RegNo]; | |
580 | Inst.addOperand(MCOperand::CreateReg(Register)); | |
581 | return Success; | |
582 | } | |
970d7e83 | 583 | |
1a4d82fc JJ |
584 | static DecodeStatus DecodeFixedPointScaleImm32(llvm::MCInst &Inst, unsigned Imm, |
585 | uint64_t Addr, | |
586 | const void *Decoder) { | |
587 | // scale{5} is asserted as 1 in tblgen. | |
588 | Imm |= 0x20; | |
589 | Inst.addOperand(MCOperand::CreateImm(64 - Imm)); | |
590 | return Success; | |
591 | } | |
970d7e83 | 592 | |
1a4d82fc JJ |
593 | static DecodeStatus DecodeFixedPointScaleImm64(llvm::MCInst &Inst, unsigned Imm, |
594 | uint64_t Addr, | |
595 | const void *Decoder) { | |
596 | Inst.addOperand(MCOperand::CreateImm(64 - Imm)); | |
597 | return Success; | |
970d7e83 LB |
598 | } |
599 | ||
1a4d82fc JJ |
600 | static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm, |
601 | uint64_t Addr, const void *Decoder) { | |
602 | int64_t ImmVal = Imm; | |
603 | const AArch64Disassembler *Dis = | |
604 | static_cast<const AArch64Disassembler *>(Decoder); | |
970d7e83 | 605 | |
1a4d82fc JJ |
606 | // Sign-extend 19-bit immediate. |
607 | if (ImmVal & (1 << (19 - 1))) | |
608 | ImmVal |= ~((1LL << 19) - 1); | |
609 | ||
610 | if (!Dis->tryAddingSymbolicOperand(Inst, ImmVal * 4, Addr, | |
611 | Inst.getOpcode() != AArch64::LDRXl, 0, 4)) | |
612 | Inst.addOperand(MCOperand::CreateImm(ImmVal)); | |
613 | return Success; | |
970d7e83 LB |
614 | } |
615 | ||
1a4d82fc JJ |
616 | static DecodeStatus DecodeMemExtend(llvm::MCInst &Inst, unsigned Imm, |
617 | uint64_t Address, const void *Decoder) { | |
618 | Inst.addOperand(MCOperand::CreateImm((Imm >> 1) & 1)); | |
619 | Inst.addOperand(MCOperand::CreateImm(Imm & 1)); | |
620 | return Success; | |
621 | } | |
970d7e83 | 622 | |
1a4d82fc JJ |
623 | static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, |
624 | uint64_t Address, | |
625 | const void *Decoder) { | |
626 | Inst.addOperand(MCOperand::CreateImm(Imm)); | |
970d7e83 | 627 | |
1a4d82fc JJ |
628 | // Every system register in the encoding space is valid with the syntax |
629 | // S<op0>_<op1>_<Cn>_<Cm>_<op2>, so decoding system registers always succeeds. | |
630 | return Success; | |
970d7e83 LB |
631 | } |
632 | ||
1a4d82fc | 633 | static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm, |
970d7e83 LB |
634 | uint64_t Address, |
635 | const void *Decoder) { | |
1a4d82fc | 636 | Inst.addOperand(MCOperand::CreateImm(Imm)); |
970d7e83 | 637 | |
1a4d82fc | 638 | return Success; |
970d7e83 LB |
639 | } |
640 | ||
1a4d82fc | 641 | static DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn, |
970d7e83 LB |
642 | uint64_t Address, |
643 | const void *Decoder) { | |
1a4d82fc JJ |
644 | // This decoder exists to add the dummy Lane operand to the MCInst, which must |
645 | // be 1 in assembly but has no other real manifestation. | |
970d7e83 LB |
646 | unsigned Rd = fieldFromInstruction(Insn, 0, 5); |
647 | unsigned Rn = fieldFromInstruction(Insn, 5, 5); | |
1a4d82fc | 648 | unsigned IsToVec = fieldFromInstruction(Insn, 16, 1); |
970d7e83 | 649 | |
1a4d82fc JJ |
650 | if (IsToVec) { |
651 | DecodeFPR128RegisterClass(Inst, Rd, Address, Decoder); | |
970d7e83 LB |
652 | DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder); |
653 | } else { | |
1a4d82fc JJ |
654 | DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder); |
655 | DecodeFPR128RegisterClass(Inst, Rn, Address, Decoder); | |
970d7e83 LB |
656 | } |
657 | ||
1a4d82fc JJ |
658 | // Add the lane |
659 | Inst.addOperand(MCOperand::CreateImm(1)); | |
970d7e83 | 660 | |
1a4d82fc JJ |
661 | return Success; |
662 | } | |
663 | ||
664 | static DecodeStatus DecodeVecShiftRImm(llvm::MCInst &Inst, unsigned Imm, | |
665 | unsigned Add) { | |
666 | Inst.addOperand(MCOperand::CreateImm(Add - Imm)); | |
667 | return Success; | |
668 | } | |
669 | ||
670 | static DecodeStatus DecodeVecShiftLImm(llvm::MCInst &Inst, unsigned Imm, | |
671 | unsigned Add) { | |
672 | Inst.addOperand(MCOperand::CreateImm((Imm + Add) & (Add - 1))); | |
673 | return Success; | |
674 | } | |
675 | ||
676 | static DecodeStatus DecodeVecShiftR64Imm(llvm::MCInst &Inst, unsigned Imm, | |
677 | uint64_t Addr, const void *Decoder) { | |
678 | return DecodeVecShiftRImm(Inst, Imm, 64); | |
679 | } | |
680 | ||
681 | static DecodeStatus DecodeVecShiftR64ImmNarrow(llvm::MCInst &Inst, unsigned Imm, | |
682 | uint64_t Addr, | |
683 | const void *Decoder) { | |
684 | return DecodeVecShiftRImm(Inst, Imm | 0x20, 64); | |
685 | } | |
686 | ||
687 | static DecodeStatus DecodeVecShiftR32Imm(llvm::MCInst &Inst, unsigned Imm, | |
688 | uint64_t Addr, const void *Decoder) { | |
689 | return DecodeVecShiftRImm(Inst, Imm, 32); | |
690 | } | |
691 | ||
692 | static DecodeStatus DecodeVecShiftR32ImmNarrow(llvm::MCInst &Inst, unsigned Imm, | |
693 | uint64_t Addr, | |
694 | const void *Decoder) { | |
695 | return DecodeVecShiftRImm(Inst, Imm | 0x10, 32); | |
696 | } | |
697 | ||
698 | static DecodeStatus DecodeVecShiftR16Imm(llvm::MCInst &Inst, unsigned Imm, | |
699 | uint64_t Addr, const void *Decoder) { | |
700 | return DecodeVecShiftRImm(Inst, Imm, 16); | |
701 | } | |
702 | ||
703 | static DecodeStatus DecodeVecShiftR16ImmNarrow(llvm::MCInst &Inst, unsigned Imm, | |
704 | uint64_t Addr, | |
705 | const void *Decoder) { | |
706 | return DecodeVecShiftRImm(Inst, Imm | 0x8, 16); | |
707 | } | |
708 | ||
709 | static DecodeStatus DecodeVecShiftR8Imm(llvm::MCInst &Inst, unsigned Imm, | |
710 | uint64_t Addr, const void *Decoder) { | |
711 | return DecodeVecShiftRImm(Inst, Imm, 8); | |
712 | } | |
713 | ||
714 | static DecodeStatus DecodeVecShiftL64Imm(llvm::MCInst &Inst, unsigned Imm, | |
715 | uint64_t Addr, const void *Decoder) { | |
716 | return DecodeVecShiftLImm(Inst, Imm, 64); | |
717 | } | |
970d7e83 | 718 | |
1a4d82fc JJ |
719 | static DecodeStatus DecodeVecShiftL32Imm(llvm::MCInst &Inst, unsigned Imm, |
720 | uint64_t Addr, const void *Decoder) { | |
721 | return DecodeVecShiftLImm(Inst, Imm, 32); | |
722 | } | |
723 | ||
724 | static DecodeStatus DecodeVecShiftL16Imm(llvm::MCInst &Inst, unsigned Imm, | |
725 | uint64_t Addr, const void *Decoder) { | |
726 | return DecodeVecShiftLImm(Inst, Imm, 16); | |
727 | } | |
728 | ||
729 | static DecodeStatus DecodeVecShiftL8Imm(llvm::MCInst &Inst, unsigned Imm, | |
730 | uint64_t Addr, const void *Decoder) { | |
731 | return DecodeVecShiftLImm(Inst, Imm, 8); | |
732 | } | |
733 | ||
734 | static DecodeStatus DecodeThreeAddrSRegInstruction(llvm::MCInst &Inst, | |
735 | uint32_t insn, uint64_t Addr, | |
736 | const void *Decoder) { | |
737 | unsigned Rd = fieldFromInstruction(insn, 0, 5); | |
738 | unsigned Rn = fieldFromInstruction(insn, 5, 5); | |
739 | unsigned Rm = fieldFromInstruction(insn, 16, 5); | |
740 | unsigned shiftHi = fieldFromInstruction(insn, 22, 2); | |
741 | unsigned shiftLo = fieldFromInstruction(insn, 10, 6); | |
742 | unsigned shift = (shiftHi << 6) | shiftLo; | |
743 | switch (Inst.getOpcode()) { | |
744 | default: | |
745 | return Fail; | |
746 | case AArch64::ADDWrs: | |
747 | case AArch64::ADDSWrs: | |
748 | case AArch64::SUBWrs: | |
749 | case AArch64::SUBSWrs: | |
750 | // if shift == '11' then ReservedValue() | |
751 | if (shiftHi == 0x3) | |
752 | return Fail; | |
753 | // Deliberate fallthrough | |
754 | case AArch64::ANDWrs: | |
755 | case AArch64::ANDSWrs: | |
756 | case AArch64::BICWrs: | |
757 | case AArch64::BICSWrs: | |
758 | case AArch64::ORRWrs: | |
759 | case AArch64::ORNWrs: | |
760 | case AArch64::EORWrs: | |
761 | case AArch64::EONWrs: { | |
762 | // if sf == '0' and imm6<5> == '1' then ReservedValue() | |
763 | if (shiftLo >> 5 == 1) | |
764 | return Fail; | |
765 | DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); | |
766 | DecodeGPR32RegisterClass(Inst, Rn, Addr, Decoder); | |
767 | DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); | |
768 | break; | |
769 | } | |
770 | case AArch64::ADDXrs: | |
771 | case AArch64::ADDSXrs: | |
772 | case AArch64::SUBXrs: | |
773 | case AArch64::SUBSXrs: | |
774 | // if shift == '11' then ReservedValue() | |
775 | if (shiftHi == 0x3) | |
776 | return Fail; | |
777 | // Deliberate fallthrough | |
778 | case AArch64::ANDXrs: | |
779 | case AArch64::ANDSXrs: | |
780 | case AArch64::BICXrs: | |
781 | case AArch64::BICSXrs: | |
782 | case AArch64::ORRXrs: | |
783 | case AArch64::ORNXrs: | |
784 | case AArch64::EORXrs: | |
785 | case AArch64::EONXrs: | |
786 | DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); | |
787 | DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder); | |
788 | DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); | |
970d7e83 | 789 | break; |
1a4d82fc JJ |
790 | } |
791 | ||
792 | Inst.addOperand(MCOperand::CreateImm(shift)); | |
793 | return Success; | |
794 | } | |
795 | ||
796 | static DecodeStatus DecodeMoveImmInstruction(llvm::MCInst &Inst, uint32_t insn, | |
797 | uint64_t Addr, | |
798 | const void *Decoder) { | |
799 | unsigned Rd = fieldFromInstruction(insn, 0, 5); | |
800 | unsigned imm = fieldFromInstruction(insn, 5, 16); | |
801 | unsigned shift = fieldFromInstruction(insn, 21, 2); | |
802 | shift <<= 4; | |
803 | switch (Inst.getOpcode()) { | |
804 | default: | |
805 | return Fail; | |
806 | case AArch64::MOVZWi: | |
807 | case AArch64::MOVNWi: | |
808 | case AArch64::MOVKWi: | |
809 | if (shift & (1U << 5)) | |
810 | return Fail; | |
811 | DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); | |
970d7e83 | 812 | break; |
1a4d82fc JJ |
813 | case AArch64::MOVZXi: |
814 | case AArch64::MOVNXi: | |
815 | case AArch64::MOVKXi: | |
816 | DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); | |
970d7e83 LB |
817 | break; |
818 | } | |
819 | ||
1a4d82fc JJ |
820 | if (Inst.getOpcode() == AArch64::MOVKWi || |
821 | Inst.getOpcode() == AArch64::MOVKXi) | |
822 | Inst.addOperand(Inst.getOperand(0)); | |
970d7e83 | 823 | |
1a4d82fc JJ |
824 | Inst.addOperand(MCOperand::CreateImm(imm)); |
825 | Inst.addOperand(MCOperand::CreateImm(shift)); | |
826 | return Success; | |
827 | } | |
970d7e83 | 828 | |
1a4d82fc JJ |
829 | static DecodeStatus DecodeUnsignedLdStInstruction(llvm::MCInst &Inst, |
830 | uint32_t insn, uint64_t Addr, | |
831 | const void *Decoder) { | |
832 | unsigned Rt = fieldFromInstruction(insn, 0, 5); | |
833 | unsigned Rn = fieldFromInstruction(insn, 5, 5); | |
834 | unsigned offset = fieldFromInstruction(insn, 10, 12); | |
835 | const AArch64Disassembler *Dis = | |
836 | static_cast<const AArch64Disassembler *>(Decoder); | |
837 | ||
838 | switch (Inst.getOpcode()) { | |
839 | default: | |
840 | return Fail; | |
841 | case AArch64::PRFMui: | |
842 | // Rt is an immediate in prefetch. | |
843 | Inst.addOperand(MCOperand::CreateImm(Rt)); | |
844 | break; | |
845 | case AArch64::STRBBui: | |
846 | case AArch64::LDRBBui: | |
847 | case AArch64::LDRSBWui: | |
848 | case AArch64::STRHHui: | |
849 | case AArch64::LDRHHui: | |
850 | case AArch64::LDRSHWui: | |
851 | case AArch64::STRWui: | |
852 | case AArch64::LDRWui: | |
853 | DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); | |
854 | break; | |
855 | case AArch64::LDRSBXui: | |
856 | case AArch64::LDRSHXui: | |
857 | case AArch64::LDRSWui: | |
858 | case AArch64::STRXui: | |
859 | case AArch64::LDRXui: | |
860 | DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); | |
861 | break; | |
862 | case AArch64::LDRQui: | |
863 | case AArch64::STRQui: | |
864 | DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); | |
865 | break; | |
866 | case AArch64::LDRDui: | |
867 | case AArch64::STRDui: | |
868 | DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); | |
869 | break; | |
870 | case AArch64::LDRSui: | |
871 | case AArch64::STRSui: | |
872 | DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); | |
873 | break; | |
874 | case AArch64::LDRHui: | |
875 | case AArch64::STRHui: | |
876 | DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); | |
877 | break; | |
878 | case AArch64::LDRBui: | |
879 | case AArch64::STRBui: | |
880 | DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); | |
881 | break; | |
882 | } | |
970d7e83 | 883 | |
1a4d82fc JJ |
884 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); |
885 | if (!Dis->tryAddingSymbolicOperand(Inst, offset, Addr, Fail, 0, 4)) | |
886 | Inst.addOperand(MCOperand::CreateImm(offset)); | |
887 | return Success; | |
970d7e83 LB |
888 | } |
889 | ||
1a4d82fc JJ |
890 | static DecodeStatus DecodeSignedLdStInstruction(llvm::MCInst &Inst, |
891 | uint32_t insn, uint64_t Addr, | |
892 | const void *Decoder) { | |
893 | unsigned Rt = fieldFromInstruction(insn, 0, 5); | |
894 | unsigned Rn = fieldFromInstruction(insn, 5, 5); | |
895 | int64_t offset = fieldFromInstruction(insn, 12, 9); | |
896 | ||
897 | // offset is a 9-bit signed immediate, so sign extend it to | |
898 | // fill the unsigned. | |
899 | if (offset & (1 << (9 - 1))) | |
900 | offset |= ~((1LL << 9) - 1); | |
901 | ||
902 | // First operand is always the writeback to the address register, if needed. | |
903 | switch (Inst.getOpcode()) { | |
904 | default: | |
905 | break; | |
906 | case AArch64::LDRSBWpre: | |
907 | case AArch64::LDRSHWpre: | |
908 | case AArch64::STRBBpre: | |
909 | case AArch64::LDRBBpre: | |
910 | case AArch64::STRHHpre: | |
911 | case AArch64::LDRHHpre: | |
912 | case AArch64::STRWpre: | |
913 | case AArch64::LDRWpre: | |
914 | case AArch64::LDRSBWpost: | |
915 | case AArch64::LDRSHWpost: | |
916 | case AArch64::STRBBpost: | |
917 | case AArch64::LDRBBpost: | |
918 | case AArch64::STRHHpost: | |
919 | case AArch64::LDRHHpost: | |
920 | case AArch64::STRWpost: | |
921 | case AArch64::LDRWpost: | |
922 | case AArch64::LDRSBXpre: | |
923 | case AArch64::LDRSHXpre: | |
924 | case AArch64::STRXpre: | |
925 | case AArch64::LDRSWpre: | |
926 | case AArch64::LDRXpre: | |
927 | case AArch64::LDRSBXpost: | |
928 | case AArch64::LDRSHXpost: | |
929 | case AArch64::STRXpost: | |
930 | case AArch64::LDRSWpost: | |
931 | case AArch64::LDRXpost: | |
932 | case AArch64::LDRQpre: | |
933 | case AArch64::STRQpre: | |
934 | case AArch64::LDRQpost: | |
935 | case AArch64::STRQpost: | |
936 | case AArch64::LDRDpre: | |
937 | case AArch64::STRDpre: | |
938 | case AArch64::LDRDpost: | |
939 | case AArch64::STRDpost: | |
940 | case AArch64::LDRSpre: | |
941 | case AArch64::STRSpre: | |
942 | case AArch64::LDRSpost: | |
943 | case AArch64::STRSpost: | |
944 | case AArch64::LDRHpre: | |
945 | case AArch64::STRHpre: | |
946 | case AArch64::LDRHpost: | |
947 | case AArch64::STRHpost: | |
948 | case AArch64::LDRBpre: | |
949 | case AArch64::STRBpre: | |
950 | case AArch64::LDRBpost: | |
951 | case AArch64::STRBpost: | |
952 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); | |
953 | break; | |
954 | } | |
970d7e83 | 955 | |
1a4d82fc JJ |
956 | switch (Inst.getOpcode()) { |
957 | default: | |
958 | return Fail; | |
959 | case AArch64::PRFUMi: | |
960 | // Rt is an immediate in prefetch. | |
961 | Inst.addOperand(MCOperand::CreateImm(Rt)); | |
962 | break; | |
963 | case AArch64::STURBBi: | |
964 | case AArch64::LDURBBi: | |
965 | case AArch64::LDURSBWi: | |
966 | case AArch64::STURHHi: | |
967 | case AArch64::LDURHHi: | |
968 | case AArch64::LDURSHWi: | |
969 | case AArch64::STURWi: | |
970 | case AArch64::LDURWi: | |
971 | case AArch64::LDTRSBWi: | |
972 | case AArch64::LDTRSHWi: | |
973 | case AArch64::STTRWi: | |
974 | case AArch64::LDTRWi: | |
975 | case AArch64::STTRHi: | |
976 | case AArch64::LDTRHi: | |
977 | case AArch64::LDTRBi: | |
978 | case AArch64::STTRBi: | |
979 | case AArch64::LDRSBWpre: | |
980 | case AArch64::LDRSHWpre: | |
981 | case AArch64::STRBBpre: | |
982 | case AArch64::LDRBBpre: | |
983 | case AArch64::STRHHpre: | |
984 | case AArch64::LDRHHpre: | |
985 | case AArch64::STRWpre: | |
986 | case AArch64::LDRWpre: | |
987 | case AArch64::LDRSBWpost: | |
988 | case AArch64::LDRSHWpost: | |
989 | case AArch64::STRBBpost: | |
990 | case AArch64::LDRBBpost: | |
991 | case AArch64::STRHHpost: | |
992 | case AArch64::LDRHHpost: | |
993 | case AArch64::STRWpost: | |
994 | case AArch64::LDRWpost: | |
995 | DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); | |
996 | break; | |
997 | case AArch64::LDURSBXi: | |
998 | case AArch64::LDURSHXi: | |
999 | case AArch64::LDURSWi: | |
1000 | case AArch64::STURXi: | |
1001 | case AArch64::LDURXi: | |
1002 | case AArch64::LDTRSBXi: | |
1003 | case AArch64::LDTRSHXi: | |
1004 | case AArch64::LDTRSWi: | |
1005 | case AArch64::STTRXi: | |
1006 | case AArch64::LDTRXi: | |
1007 | case AArch64::LDRSBXpre: | |
1008 | case AArch64::LDRSHXpre: | |
1009 | case AArch64::STRXpre: | |
1010 | case AArch64::LDRSWpre: | |
1011 | case AArch64::LDRXpre: | |
1012 | case AArch64::LDRSBXpost: | |
1013 | case AArch64::LDRSHXpost: | |
1014 | case AArch64::STRXpost: | |
1015 | case AArch64::LDRSWpost: | |
1016 | case AArch64::LDRXpost: | |
1017 | DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); | |
1018 | break; | |
1019 | case AArch64::LDURQi: | |
1020 | case AArch64::STURQi: | |
1021 | case AArch64::LDRQpre: | |
1022 | case AArch64::STRQpre: | |
1023 | case AArch64::LDRQpost: | |
1024 | case AArch64::STRQpost: | |
1025 | DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); | |
1026 | break; | |
1027 | case AArch64::LDURDi: | |
1028 | case AArch64::STURDi: | |
1029 | case AArch64::LDRDpre: | |
1030 | case AArch64::STRDpre: | |
1031 | case AArch64::LDRDpost: | |
1032 | case AArch64::STRDpost: | |
1033 | DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); | |
1034 | break; | |
1035 | case AArch64::LDURSi: | |
1036 | case AArch64::STURSi: | |
1037 | case AArch64::LDRSpre: | |
1038 | case AArch64::STRSpre: | |
1039 | case AArch64::LDRSpost: | |
1040 | case AArch64::STRSpost: | |
1041 | DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); | |
1042 | break; | |
1043 | case AArch64::LDURHi: | |
1044 | case AArch64::STURHi: | |
1045 | case AArch64::LDRHpre: | |
1046 | case AArch64::STRHpre: | |
1047 | case AArch64::LDRHpost: | |
1048 | case AArch64::STRHpost: | |
1049 | DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); | |
1050 | break; | |
1051 | case AArch64::LDURBi: | |
1052 | case AArch64::STURBi: | |
1053 | case AArch64::LDRBpre: | |
1054 | case AArch64::STRBpre: | |
1055 | case AArch64::LDRBpost: | |
1056 | case AArch64::STRBpost: | |
1057 | DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); | |
1058 | break; | |
970d7e83 LB |
1059 | } |
1060 | ||
1a4d82fc JJ |
1061 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); |
1062 | Inst.addOperand(MCOperand::CreateImm(offset)); | |
970d7e83 | 1063 | |
1a4d82fc JJ |
1064 | bool IsLoad = fieldFromInstruction(insn, 22, 1); |
1065 | bool IsIndexed = fieldFromInstruction(insn, 10, 2) != 0; | |
1066 | bool IsFP = fieldFromInstruction(insn, 26, 1); | |
1067 | ||
1068 | // Cannot write back to a transfer register (but xzr != sp). | |
1069 | if (IsLoad && IsIndexed && !IsFP && Rn != 31 && Rt == Rn) | |
1070 | return SoftFail; | |
1071 | ||
1072 | return Success; | |
970d7e83 LB |
1073 | } |
1074 | ||
1a4d82fc JJ |
1075 | static DecodeStatus DecodeExclusiveLdStInstruction(llvm::MCInst &Inst, |
1076 | uint32_t insn, uint64_t Addr, | |
1077 | const void *Decoder) { | |
1078 | unsigned Rt = fieldFromInstruction(insn, 0, 5); | |
1079 | unsigned Rn = fieldFromInstruction(insn, 5, 5); | |
1080 | unsigned Rt2 = fieldFromInstruction(insn, 10, 5); | |
1081 | unsigned Rs = fieldFromInstruction(insn, 16, 5); | |
1082 | ||
1083 | unsigned Opcode = Inst.getOpcode(); | |
1084 | switch (Opcode) { | |
1085 | default: | |
1086 | return Fail; | |
1087 | case AArch64::STLXRW: | |
1088 | case AArch64::STLXRB: | |
1089 | case AArch64::STLXRH: | |
1090 | case AArch64::STXRW: | |
1091 | case AArch64::STXRB: | |
1092 | case AArch64::STXRH: | |
1093 | DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); | |
1094 | // FALLTHROUGH | |
1095 | case AArch64::LDARW: | |
1096 | case AArch64::LDARB: | |
1097 | case AArch64::LDARH: | |
1098 | case AArch64::LDAXRW: | |
1099 | case AArch64::LDAXRB: | |
1100 | case AArch64::LDAXRH: | |
1101 | case AArch64::LDXRW: | |
1102 | case AArch64::LDXRB: | |
1103 | case AArch64::LDXRH: | |
1104 | case AArch64::STLRW: | |
1105 | case AArch64::STLRB: | |
1106 | case AArch64::STLRH: | |
1107 | DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); | |
1108 | break; | |
1109 | case AArch64::STLXRX: | |
1110 | case AArch64::STXRX: | |
1111 | DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); | |
1112 | // FALLTHROUGH | |
1113 | case AArch64::LDARX: | |
1114 | case AArch64::LDAXRX: | |
1115 | case AArch64::LDXRX: | |
1116 | case AArch64::STLRX: | |
1117 | DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); | |
1118 | break; | |
1119 | case AArch64::STLXPW: | |
1120 | case AArch64::STXPW: | |
1121 | DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); | |
1122 | // FALLTHROUGH | |
1123 | case AArch64::LDAXPW: | |
1124 | case AArch64::LDXPW: | |
1125 | DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); | |
1126 | DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder); | |
1127 | break; | |
1128 | case AArch64::STLXPX: | |
1129 | case AArch64::STXPX: | |
1130 | DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); | |
1131 | // FALLTHROUGH | |
1132 | case AArch64::LDAXPX: | |
1133 | case AArch64::LDXPX: | |
1134 | DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); | |
1135 | DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder); | |
1136 | break; | |
1137 | } | |
1138 | ||
1139 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); | |
970d7e83 | 1140 | |
1a4d82fc JJ |
1141 | // You shouldn't load to the same register twice in an instruction... |
1142 | if ((Opcode == AArch64::LDAXPW || Opcode == AArch64::LDXPW || | |
1143 | Opcode == AArch64::LDAXPX || Opcode == AArch64::LDXPX) && | |
1144 | Rt == Rt2) | |
1145 | return SoftFail; | |
1146 | ||
1147 | return Success; | |
1148 | } | |
1149 | ||
1150 | static DecodeStatus DecodePairLdStInstruction(llvm::MCInst &Inst, uint32_t insn, | |
1151 | uint64_t Addr, | |
970d7e83 | 1152 | const void *Decoder) { |
1a4d82fc JJ |
1153 | unsigned Rt = fieldFromInstruction(insn, 0, 5); |
1154 | unsigned Rn = fieldFromInstruction(insn, 5, 5); | |
1155 | unsigned Rt2 = fieldFromInstruction(insn, 10, 5); | |
1156 | int64_t offset = fieldFromInstruction(insn, 15, 7); | |
1157 | bool IsLoad = fieldFromInstruction(insn, 22, 1); | |
1158 | ||
1159 | // offset is a 7-bit signed immediate, so sign extend it to | |
1160 | // fill the unsigned. | |
1161 | if (offset & (1 << (7 - 1))) | |
1162 | offset |= ~((1LL << 7) - 1); | |
1163 | ||
1164 | unsigned Opcode = Inst.getOpcode(); | |
1165 | bool NeedsDisjointWritebackTransfer = false; | |
1166 | ||
1167 | // First operand is always writeback of base register. | |
1168 | switch (Opcode) { | |
1169 | default: | |
1170 | break; | |
1171 | case AArch64::LDPXpost: | |
1172 | case AArch64::STPXpost: | |
1173 | case AArch64::LDPSWpost: | |
1174 | case AArch64::LDPXpre: | |
1175 | case AArch64::STPXpre: | |
1176 | case AArch64::LDPSWpre: | |
1177 | case AArch64::LDPWpost: | |
1178 | case AArch64::STPWpost: | |
1179 | case AArch64::LDPWpre: | |
1180 | case AArch64::STPWpre: | |
1181 | case AArch64::LDPQpost: | |
1182 | case AArch64::STPQpost: | |
1183 | case AArch64::LDPQpre: | |
1184 | case AArch64::STPQpre: | |
1185 | case AArch64::LDPDpost: | |
1186 | case AArch64::STPDpost: | |
1187 | case AArch64::LDPDpre: | |
1188 | case AArch64::STPDpre: | |
1189 | case AArch64::LDPSpost: | |
1190 | case AArch64::STPSpost: | |
1191 | case AArch64::LDPSpre: | |
1192 | case AArch64::STPSpre: | |
1193 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); | |
1194 | break; | |
970d7e83 LB |
1195 | } |
1196 | ||
1a4d82fc JJ |
1197 | switch (Opcode) { |
1198 | default: | |
1199 | return Fail; | |
1200 | case AArch64::LDPXpost: | |
1201 | case AArch64::STPXpost: | |
1202 | case AArch64::LDPSWpost: | |
1203 | case AArch64::LDPXpre: | |
1204 | case AArch64::STPXpre: | |
1205 | case AArch64::LDPSWpre: | |
1206 | NeedsDisjointWritebackTransfer = true; | |
1207 | // Fallthrough | |
1208 | case AArch64::LDNPXi: | |
1209 | case AArch64::STNPXi: | |
1210 | case AArch64::LDPXi: | |
1211 | case AArch64::STPXi: | |
1212 | case AArch64::LDPSWi: | |
1213 | DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); | |
1214 | DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder); | |
1215 | break; | |
1216 | case AArch64::LDPWpost: | |
1217 | case AArch64::STPWpost: | |
1218 | case AArch64::LDPWpre: | |
1219 | case AArch64::STPWpre: | |
1220 | NeedsDisjointWritebackTransfer = true; | |
1221 | // Fallthrough | |
1222 | case AArch64::LDNPWi: | |
1223 | case AArch64::STNPWi: | |
1224 | case AArch64::LDPWi: | |
1225 | case AArch64::STPWi: | |
1226 | DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); | |
1227 | DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder); | |
1228 | break; | |
1229 | case AArch64::LDNPQi: | |
1230 | case AArch64::STNPQi: | |
1231 | case AArch64::LDPQpost: | |
1232 | case AArch64::STPQpost: | |
1233 | case AArch64::LDPQi: | |
1234 | case AArch64::STPQi: | |
1235 | case AArch64::LDPQpre: | |
1236 | case AArch64::STPQpre: | |
1237 | DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); | |
1238 | DecodeFPR128RegisterClass(Inst, Rt2, Addr, Decoder); | |
1239 | break; | |
1240 | case AArch64::LDNPDi: | |
1241 | case AArch64::STNPDi: | |
1242 | case AArch64::LDPDpost: | |
1243 | case AArch64::STPDpost: | |
1244 | case AArch64::LDPDi: | |
1245 | case AArch64::STPDi: | |
1246 | case AArch64::LDPDpre: | |
1247 | case AArch64::STPDpre: | |
1248 | DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); | |
1249 | DecodeFPR64RegisterClass(Inst, Rt2, Addr, Decoder); | |
1250 | break; | |
1251 | case AArch64::LDNPSi: | |
1252 | case AArch64::STNPSi: | |
1253 | case AArch64::LDPSpost: | |
1254 | case AArch64::STPSpost: | |
1255 | case AArch64::LDPSi: | |
1256 | case AArch64::STPSi: | |
1257 | case AArch64::LDPSpre: | |
1258 | case AArch64::STPSpre: | |
1259 | DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); | |
1260 | DecodeFPR32RegisterClass(Inst, Rt2, Addr, Decoder); | |
1261 | break; | |
1262 | } | |
1263 | ||
1264 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); | |
1265 | Inst.addOperand(MCOperand::CreateImm(offset)); | |
1266 | ||
970d7e83 | 1267 | // You shouldn't load to the same register twice in an instruction... |
1a4d82fc JJ |
1268 | if (IsLoad && Rt == Rt2) |
1269 | return SoftFail; | |
970d7e83 LB |
1270 | |
1271 | // ... or do any operation that writes-back to a transfer register. But note | |
1272 | // that "stp xzr, xzr, [sp], #4" is fine because xzr and sp are different. | |
1a4d82fc JJ |
1273 | if (NeedsDisjointWritebackTransfer && Rn != 31 && (Rt == Rn || Rt2 == Rn)) |
1274 | return SoftFail; | |
970d7e83 | 1275 | |
1a4d82fc JJ |
1276 | return Success; |
1277 | } | |
1278 | ||
1279 | static DecodeStatus DecodeAddSubERegInstruction(llvm::MCInst &Inst, | |
1280 | uint32_t insn, uint64_t Addr, | |
1281 | const void *Decoder) { | |
1282 | unsigned Rd = fieldFromInstruction(insn, 0, 5); | |
1283 | unsigned Rn = fieldFromInstruction(insn, 5, 5); | |
1284 | unsigned Rm = fieldFromInstruction(insn, 16, 5); | |
1285 | unsigned extend = fieldFromInstruction(insn, 10, 6); | |
1286 | ||
1287 | unsigned shift = extend & 0x7; | |
1288 | if (shift > 4) | |
1289 | return Fail; | |
1290 | ||
1291 | switch (Inst.getOpcode()) { | |
1292 | default: | |
1293 | return Fail; | |
1294 | case AArch64::ADDWrx: | |
1295 | case AArch64::SUBWrx: | |
1296 | DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder); | |
1297 | DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder); | |
1298 | DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); | |
1299 | break; | |
1300 | case AArch64::ADDSWrx: | |
1301 | case AArch64::SUBSWrx: | |
1302 | DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); | |
1303 | DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder); | |
1304 | DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); | |
1305 | break; | |
1306 | case AArch64::ADDXrx: | |
1307 | case AArch64::SUBXrx: | |
1308 | DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); | |
1309 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); | |
1310 | DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); | |
1311 | break; | |
1312 | case AArch64::ADDSXrx: | |
1313 | case AArch64::SUBSXrx: | |
1314 | DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); | |
1315 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); | |
1316 | DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); | |
1317 | break; | |
1318 | case AArch64::ADDXrx64: | |
1319 | case AArch64::SUBXrx64: | |
1320 | DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); | |
1321 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); | |
1322 | DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); | |
1323 | break; | |
1324 | case AArch64::SUBSXrx64: | |
1325 | case AArch64::ADDSXrx64: | |
1326 | DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); | |
1327 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); | |
1328 | DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); | |
1329 | break; | |
970d7e83 LB |
1330 | } |
1331 | ||
1a4d82fc JJ |
1332 | Inst.addOperand(MCOperand::CreateImm(extend)); |
1333 | return Success; | |
1334 | } | |
970d7e83 | 1335 | |
1a4d82fc JJ |
1336 | static DecodeStatus DecodeLogicalImmInstruction(llvm::MCInst &Inst, |
1337 | uint32_t insn, uint64_t Addr, | |
1338 | const void *Decoder) { | |
1339 | unsigned Rd = fieldFromInstruction(insn, 0, 5); | |
1340 | unsigned Rn = fieldFromInstruction(insn, 5, 5); | |
1341 | unsigned Datasize = fieldFromInstruction(insn, 31, 1); | |
1342 | unsigned imm; | |
1343 | ||
1344 | if (Datasize) { | |
1345 | if (Inst.getOpcode() == AArch64::ANDSXri) | |
1346 | DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); | |
1347 | else | |
1348 | DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); | |
1349 | DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder); | |
1350 | imm = fieldFromInstruction(insn, 10, 13); | |
1351 | if (!AArch64_AM::isValidDecodeLogicalImmediate(imm, 64)) | |
1352 | return Fail; | |
1353 | } else { | |
1354 | if (Inst.getOpcode() == AArch64::ANDSWri) | |
1355 | DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); | |
1356 | else | |
1357 | DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder); | |
1358 | DecodeGPR32RegisterClass(Inst, Rn, Addr, Decoder); | |
1359 | imm = fieldFromInstruction(insn, 10, 12); | |
1360 | if (!AArch64_AM::isValidDecodeLogicalImmediate(imm, 32)) | |
1361 | return Fail; | |
970d7e83 | 1362 | } |
1a4d82fc JJ |
1363 | Inst.addOperand(MCOperand::CreateImm(imm)); |
1364 | return Success; | |
1365 | } | |
970d7e83 | 1366 | |
1a4d82fc JJ |
1367 | static DecodeStatus DecodeModImmInstruction(llvm::MCInst &Inst, uint32_t insn, |
1368 | uint64_t Addr, | |
1369 | const void *Decoder) { | |
1370 | unsigned Rd = fieldFromInstruction(insn, 0, 5); | |
1371 | unsigned cmode = fieldFromInstruction(insn, 12, 4); | |
1372 | unsigned imm = fieldFromInstruction(insn, 16, 3) << 5; | |
1373 | imm |= fieldFromInstruction(insn, 5, 5); | |
970d7e83 | 1374 | |
1a4d82fc JJ |
1375 | if (Inst.getOpcode() == AArch64::MOVID) |
1376 | DecodeFPR64RegisterClass(Inst, Rd, Addr, Decoder); | |
1377 | else | |
1378 | DecodeVectorRegisterClass(Inst, Rd, Addr, Decoder); | |
970d7e83 | 1379 | |
1a4d82fc JJ |
1380 | Inst.addOperand(MCOperand::CreateImm(imm)); |
1381 | ||
1382 | switch (Inst.getOpcode()) { | |
1383 | default: | |
1384 | break; | |
1385 | case AArch64::MOVIv4i16: | |
1386 | case AArch64::MOVIv8i16: | |
1387 | case AArch64::MVNIv4i16: | |
1388 | case AArch64::MVNIv8i16: | |
1389 | case AArch64::MOVIv2i32: | |
1390 | case AArch64::MOVIv4i32: | |
1391 | case AArch64::MVNIv2i32: | |
1392 | case AArch64::MVNIv4i32: | |
1393 | Inst.addOperand(MCOperand::CreateImm((cmode & 6) << 2)); | |
1394 | break; | |
1395 | case AArch64::MOVIv2s_msl: | |
1396 | case AArch64::MOVIv4s_msl: | |
1397 | case AArch64::MVNIv2s_msl: | |
1398 | case AArch64::MVNIv4s_msl: | |
1399 | Inst.addOperand(MCOperand::CreateImm(cmode & 1 ? 0x110 : 0x108)); | |
1400 | break; | |
970d7e83 LB |
1401 | } |
1402 | ||
1a4d82fc | 1403 | return Success; |
970d7e83 LB |
1404 | } |
1405 | ||
1a4d82fc JJ |
1406 | static DecodeStatus DecodeModImmTiedInstruction(llvm::MCInst &Inst, |
1407 | uint32_t insn, uint64_t Addr, | |
1408 | const void *Decoder) { | |
1409 | unsigned Rd = fieldFromInstruction(insn, 0, 5); | |
1410 | unsigned cmode = fieldFromInstruction(insn, 12, 4); | |
1411 | unsigned imm = fieldFromInstruction(insn, 16, 3) << 5; | |
1412 | imm |= fieldFromInstruction(insn, 5, 5); | |
970d7e83 | 1413 | |
1a4d82fc JJ |
1414 | // Tied operands added twice. |
1415 | DecodeVectorRegisterClass(Inst, Rd, Addr, Decoder); | |
1416 | DecodeVectorRegisterClass(Inst, Rd, Addr, Decoder); | |
970d7e83 | 1417 | |
1a4d82fc JJ |
1418 | Inst.addOperand(MCOperand::CreateImm(imm)); |
1419 | Inst.addOperand(MCOperand::CreateImm((cmode & 6) << 2)); | |
970d7e83 | 1420 | |
1a4d82fc | 1421 | return Success; |
970d7e83 LB |
1422 | } |
1423 | ||
1a4d82fc JJ |
1424 | static DecodeStatus DecodeAdrInstruction(llvm::MCInst &Inst, uint32_t insn, |
1425 | uint64_t Addr, const void *Decoder) { | |
1426 | unsigned Rd = fieldFromInstruction(insn, 0, 5); | |
1427 | int64_t imm = fieldFromInstruction(insn, 5, 19) << 2; | |
1428 | imm |= fieldFromInstruction(insn, 29, 2); | |
1429 | const AArch64Disassembler *Dis = | |
1430 | static_cast<const AArch64Disassembler *>(Decoder); | |
970d7e83 | 1431 | |
1a4d82fc JJ |
1432 | // Sign-extend the 21-bit immediate. |
1433 | if (imm & (1 << (21 - 1))) | |
1434 | imm |= ~((1LL << 21) - 1); | |
970d7e83 | 1435 | |
1a4d82fc JJ |
1436 | DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); |
1437 | if (!Dis->tryAddingSymbolicOperand(Inst, imm, Addr, Fail, 0, 4)) | |
1438 | Inst.addOperand(MCOperand::CreateImm(imm)); | |
970d7e83 | 1439 | |
1a4d82fc JJ |
1440 | return Success; |
1441 | } | |
970d7e83 | 1442 | |
1a4d82fc JJ |
1443 | static DecodeStatus DecodeBaseAddSubImm(llvm::MCInst &Inst, uint32_t insn, |
1444 | uint64_t Addr, const void *Decoder) { | |
1445 | unsigned Rd = fieldFromInstruction(insn, 0, 5); | |
1446 | unsigned Rn = fieldFromInstruction(insn, 5, 5); | |
1447 | unsigned Imm = fieldFromInstruction(insn, 10, 14); | |
1448 | unsigned S = fieldFromInstruction(insn, 29, 1); | |
1449 | unsigned Datasize = fieldFromInstruction(insn, 31, 1); | |
1450 | ||
1451 | unsigned ShifterVal = (Imm >> 12) & 3; | |
1452 | unsigned ImmVal = Imm & 0xFFF; | |
1453 | const AArch64Disassembler *Dis = | |
1454 | static_cast<const AArch64Disassembler *>(Decoder); | |
1455 | ||
1456 | if (ShifterVal != 0 && ShifterVal != 1) | |
1457 | return Fail; | |
1458 | ||
1459 | if (Datasize) { | |
1460 | if (Rd == 31 && !S) | |
1461 | DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); | |
1462 | else | |
1463 | DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); | |
1464 | DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); | |
970d7e83 | 1465 | } else { |
1a4d82fc JJ |
1466 | if (Rd == 31 && !S) |
1467 | DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder); | |
1468 | else | |
1469 | DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); | |
1470 | DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder); | |
970d7e83 LB |
1471 | } |
1472 | ||
1a4d82fc JJ |
1473 | if (!Dis->tryAddingSymbolicOperand(Inst, Imm, Addr, Fail, 0, 4)) |
1474 | Inst.addOperand(MCOperand::CreateImm(ImmVal)); | |
1475 | Inst.addOperand(MCOperand::CreateImm(12 * ShifterVal)); | |
1476 | return Success; | |
1477 | } | |
970d7e83 | 1478 | |
1a4d82fc JJ |
1479 | static DecodeStatus DecodeUnconditionalBranch(llvm::MCInst &Inst, uint32_t insn, |
1480 | uint64_t Addr, | |
1481 | const void *Decoder) { | |
1482 | int64_t imm = fieldFromInstruction(insn, 0, 26); | |
1483 | const AArch64Disassembler *Dis = | |
1484 | static_cast<const AArch64Disassembler *>(Decoder); | |
970d7e83 | 1485 | |
1a4d82fc JJ |
1486 | // Sign-extend the 26-bit immediate. |
1487 | if (imm & (1 << (26 - 1))) | |
1488 | imm |= ~((1LL << 26) - 1); | |
970d7e83 | 1489 | |
1a4d82fc JJ |
1490 | if (!Dis->tryAddingSymbolicOperand(Inst, imm * 4, Addr, true, 0, 4)) |
1491 | Inst.addOperand(MCOperand::CreateImm(imm)); | |
970d7e83 | 1492 | |
1a4d82fc | 1493 | return Success; |
970d7e83 LB |
1494 | } |
1495 | ||
1a4d82fc JJ |
1496 | static DecodeStatus DecodeSystemPStateInstruction(llvm::MCInst &Inst, |
1497 | uint32_t insn, uint64_t Addr, | |
1498 | const void *Decoder) { | |
1499 | uint64_t op1 = fieldFromInstruction(insn, 16, 3); | |
1500 | uint64_t op2 = fieldFromInstruction(insn, 5, 3); | |
1501 | uint64_t crm = fieldFromInstruction(insn, 8, 4); | |
1502 | ||
1503 | uint64_t pstate_field = (op1 << 3) | op2; | |
1504 | ||
1505 | Inst.addOperand(MCOperand::CreateImm(pstate_field)); | |
1506 | Inst.addOperand(MCOperand::CreateImm(crm)); | |
1507 | ||
1508 | bool ValidNamed; | |
1509 | (void)AArch64PState::PStateMapper().toString(pstate_field, ValidNamed); | |
1510 | ||
1511 | return ValidNamed ? Success : Fail; | |
970d7e83 LB |
1512 | } |
1513 | ||
1a4d82fc JJ |
1514 | static DecodeStatus DecodeTestAndBranch(llvm::MCInst &Inst, uint32_t insn, |
1515 | uint64_t Addr, const void *Decoder) { | |
1516 | uint64_t Rt = fieldFromInstruction(insn, 0, 5); | |
1517 | uint64_t bit = fieldFromInstruction(insn, 31, 1) << 5; | |
1518 | bit |= fieldFromInstruction(insn, 19, 5); | |
1519 | int64_t dst = fieldFromInstruction(insn, 5, 14); | |
1520 | const AArch64Disassembler *Dis = | |
1521 | static_cast<const AArch64Disassembler *>(Decoder); | |
1522 | ||
1523 | // Sign-extend 14-bit immediate. | |
1524 | if (dst & (1 << (14 - 1))) | |
1525 | dst |= ~((1LL << 14) - 1); | |
1526 | ||
1527 | if (fieldFromInstruction(insn, 31, 1) == 0) | |
1528 | DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); | |
1529 | else | |
1530 | DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); | |
1531 | Inst.addOperand(MCOperand::CreateImm(bit)); | |
1532 | if (!Dis->tryAddingSymbolicOperand(Inst, dst * 4, Addr, true, 0, 4)) | |
1533 | Inst.addOperand(MCOperand::CreateImm(dst)); | |
970d7e83 | 1534 | |
1a4d82fc JJ |
1535 | return Success; |
1536 | } |