1249259Sdim//===- AArch64Disassembler.cpp - Disassembler for AArch64 ISA -------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// This file contains the functions necessary to decode AArch64 instruction
11249259Sdim// bitpatterns into MCInsts (with the help of TableGenerated information from
12249259Sdim// the instruction definitions).
13249259Sdim//
14249259Sdim//===----------------------------------------------------------------------===//
15249259Sdim
16249259Sdim#define DEBUG_TYPE "arm-disassembler"
17249259Sdim
18249259Sdim#include "AArch64.h"
19249259Sdim#include "AArch64RegisterInfo.h"
20249259Sdim#include "AArch64Subtarget.h"
21249259Sdim#include "Utils/AArch64BaseInfo.h"
22249259Sdim#include "llvm/MC/MCInst.h"
23249259Sdim#include "llvm/MC/MCInstrDesc.h"
24249259Sdim#include "llvm/MC/MCExpr.h"
25249259Sdim#include "llvm/MC/MCContext.h"
26249259Sdim#include "llvm/MC/MCDisassembler.h"
27249259Sdim#include "llvm/MC/MCFixedLenDisassembler.h"
28249259Sdim#include "llvm/Support/Debug.h"
29249259Sdim#include "llvm/Support/MemoryObject.h"
30249259Sdim#include "llvm/Support/ErrorHandling.h"
31249259Sdim#include "llvm/Support/TargetRegistry.h"
32249259Sdim#include "llvm/Support/raw_ostream.h"
33249259Sdim
34249259Sdimusing namespace llvm;
35249259Sdim
36249259Sdimtypedef MCDisassembler::DecodeStatus DecodeStatus;
37249259Sdim
38249259Sdimnamespace {
39249259Sdim/// AArch64 disassembler for all AArch64 platforms.
40249259Sdimclass AArch64Disassembler : public MCDisassembler {
41263508Sdim  OwningPtr<const MCRegisterInfo> RegInfo;
42249259Sdimpublic:
43249259Sdim  /// Initializes the disassembler.
44249259Sdim  ///
45249259Sdim  AArch64Disassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info)
46249259Sdim    : MCDisassembler(STI), RegInfo(Info) {
47249259Sdim  }
48249259Sdim
49263508Sdim  ~AArch64Disassembler() {}
50249259Sdim
51249259Sdim  /// See MCDisassembler.
52249259Sdim  DecodeStatus getInstruction(MCInst &instr,
53249259Sdim                              uint64_t &size,
54249259Sdim                              const MemoryObject &region,
55249259Sdim                              uint64_t address,
56249259Sdim                              raw_ostream &vStream,
57249259Sdim                              raw_ostream &cStream) const;
58249259Sdim
59263508Sdim  const MCRegisterInfo *getRegInfo() const { return RegInfo.get(); }
60249259Sdim};
61249259Sdim
62249259Sdim}
63249259Sdim
64249259Sdim// Forward-declarations used in the auto-generated files.
65249259Sdimstatic DecodeStatus DecodeGPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
66249259Sdim                                         uint64_t Address, const void *Decoder);
67249259Sdimstatic DecodeStatus
68249259SdimDecodeGPR64xspRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
69249259Sdim                            uint64_t Address, const void *Decoder);
70249259Sdim
71249259Sdimstatic DecodeStatus DecodeGPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
72249259Sdim                                         uint64_t Address, const void *Decoder);
73249259Sdimstatic DecodeStatus
74249259SdimDecodeGPR32wspRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
75249259Sdim                            uint64_t Address, const void *Decoder);
76249259Sdim
77249259Sdimstatic DecodeStatus DecodeFPR8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
78249259Sdim                                         uint64_t Address, const void *Decoder);
79249259Sdimstatic DecodeStatus DecodeFPR16RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
80249259Sdim                                         uint64_t Address, const void *Decoder);
81249259Sdimstatic DecodeStatus DecodeFPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
82249259Sdim                                         uint64_t Address, const void *Decoder);
83249259Sdimstatic DecodeStatus DecodeFPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
84249259Sdim                                         uint64_t Address, const void *Decoder);
85263508Sdimstatic DecodeStatus DecodeFPR64LoRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
86263508Sdim                                         uint64_t Address, const void *Decoder);
87249259Sdimstatic DecodeStatus DecodeFPR128RegisterClass(llvm::MCInst &Inst,
88249259Sdim                                              unsigned RegNo, uint64_t Address,
89249259Sdim                                              const void *Decoder);
90263508Sdimstatic DecodeStatus DecodeFPR128LoRegisterClass(llvm::MCInst &Inst,
91263508Sdim                                                unsigned RegNo, uint64_t Address,
92263508Sdim                                                const void *Decoder);
93249259Sdim
94263508Sdimstatic DecodeStatus DecodeGPR64noxzrRegisterClass(llvm::MCInst &Inst,
95263508Sdim                                                  unsigned RegNo,
96263508Sdim                                                  uint64_t Address,
97263508Sdim                                                  const void *Decoder);
98263508Sdim
99263508Sdimstatic DecodeStatus DecodeDPairRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
100263508Sdim                                             uint64_t Address,
101263508Sdim                                             const void *Decoder);
102263508Sdimstatic DecodeStatus DecodeQPairRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
103263508Sdim                                             uint64_t Address,
104263508Sdim                                             const void *Decoder);
105263508Sdimstatic DecodeStatus DecodeDTripleRegisterClass(llvm::MCInst &Inst,
106263508Sdim                                               unsigned RegNo, uint64_t Address,
107263508Sdim                                               const void *Decoder);
108263508Sdimstatic DecodeStatus DecodeQTripleRegisterClass(llvm::MCInst &Inst,
109263508Sdim                                               unsigned RegNo, uint64_t Address,
110263508Sdim                                               const void *Decoder);
111263508Sdimstatic DecodeStatus DecodeDQuadRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
112263508Sdim                                             uint64_t Address,
113263508Sdim                                             const void *Decoder);
114263508Sdimstatic DecodeStatus DecodeQQuadRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
115263508Sdim                                             uint64_t Address,
116263508Sdim                                             const void *Decoder);
117263508Sdim
118249259Sdimstatic DecodeStatus DecodeAddrRegExtendOperand(llvm::MCInst &Inst,
119249259Sdim                                               unsigned OptionHiS,
120249259Sdim                                               uint64_t Address,
121249259Sdim                                               const void *Decoder);
122249259Sdim
123249259Sdim
124249259Sdimstatic DecodeStatus DecodeBitfield32ImmOperand(llvm::MCInst &Inst,
125249259Sdim                                               unsigned Imm6Bits,
126249259Sdim                                               uint64_t Address,
127249259Sdim                                               const void *Decoder);
128249259Sdim
129249259Sdimstatic DecodeStatus DecodeCVT32FixedPosOperand(llvm::MCInst &Inst,
130249259Sdim                                               unsigned Imm6Bits,
131249259Sdim                                               uint64_t Address,
132249259Sdim                                               const void *Decoder);
133249259Sdim
134249259Sdimstatic DecodeStatus DecodeFPZeroOperand(llvm::MCInst &Inst,
135249259Sdim                                        unsigned RmBits,
136249259Sdim                                        uint64_t Address,
137249259Sdim                                        const void *Decoder);
138249259Sdim
139263508Sdimstatic DecodeStatus DecodeShiftRightImm8(MCInst &Inst, unsigned Val,
140263508Sdim                                         uint64_t Address, const void *Decoder);
141263508Sdimstatic DecodeStatus DecodeShiftRightImm16(MCInst &Inst, unsigned Val,
142263508Sdim                                          uint64_t Address,
143263508Sdim                                          const void *Decoder);
144263508Sdimstatic DecodeStatus DecodeShiftRightImm32(MCInst &Inst, unsigned Val,
145263508Sdim                                          uint64_t Address,
146263508Sdim                                          const void *Decoder);
147263508Sdimstatic DecodeStatus DecodeShiftRightImm64(MCInst &Inst, unsigned Val,
148263508Sdim                                          uint64_t Address,
149263508Sdim                                          const void *Decoder);
150263508Sdim
151263508Sdimstatic DecodeStatus DecodeShiftLeftImm8(MCInst &Inst, unsigned Val,
152263508Sdim                                        uint64_t Address, const void *Decoder);
153263508Sdimstatic DecodeStatus DecodeShiftLeftImm16(MCInst &Inst, unsigned Val,
154263508Sdim                                         uint64_t Address,
155263508Sdim                                         const void *Decoder);
156263508Sdimstatic DecodeStatus DecodeShiftLeftImm32(MCInst &Inst, unsigned Val,
157263508Sdim                                         uint64_t Address,
158263508Sdim                                         const void *Decoder);
159263508Sdimstatic DecodeStatus DecodeShiftLeftImm64(MCInst &Inst, unsigned Val,
160263508Sdim                                         uint64_t Address,
161263508Sdim                                         const void *Decoder);
162263508Sdim
163249259Sdimtemplate<int RegWidth>
164249259Sdimstatic DecodeStatus DecodeMoveWideImmOperand(llvm::MCInst &Inst,
165249259Sdim                                             unsigned FullImm,
166249259Sdim                                             uint64_t Address,
167249259Sdim                                             const void *Decoder);
168249259Sdim
169249259Sdimtemplate<int RegWidth>
170249259Sdimstatic DecodeStatus DecodeLogicalImmOperand(llvm::MCInst &Inst,
171249259Sdim                                            unsigned Bits,
172249259Sdim                                            uint64_t Address,
173249259Sdim                                            const void *Decoder);
174249259Sdim
175249259Sdimstatic DecodeStatus DecodeRegExtendOperand(llvm::MCInst &Inst,
176249259Sdim                                           unsigned ShiftAmount,
177249259Sdim                                           uint64_t Address,
178249259Sdim                                           const void *Decoder);
179263508Sdimtemplate <A64SE::ShiftExtSpecifiers Ext, bool IsHalf>
180263508Sdimstatic DecodeStatus
181263508SdimDecodeNeonMovImmShiftOperand(llvm::MCInst &Inst, unsigned ShiftAmount,
182263508Sdim                             uint64_t Address, const void *Decoder);
183249259Sdim
184249259Sdimstatic DecodeStatus Decode32BitShiftOperand(llvm::MCInst &Inst,
185249259Sdim                                            unsigned ShiftAmount,
186249259Sdim                                            uint64_t Address,
187249259Sdim                                            const void *Decoder);
188249259Sdimstatic DecodeStatus DecodeBitfieldInstruction(llvm::MCInst &Inst, unsigned Insn,
189249259Sdim                                              uint64_t Address,
190249259Sdim                                              const void *Decoder);
191249259Sdim
192249259Sdimstatic DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn,
193249259Sdim                                              uint64_t Address,
194249259Sdim                                              const void *Decoder);
195249259Sdim
196249259Sdimstatic DecodeStatus DecodeLDSTPairInstruction(llvm::MCInst &Inst,
197249259Sdim                                              unsigned Insn,
198249259Sdim                                              uint64_t Address,
199249259Sdim                                              const void *Decoder);
200249259Sdim
201249259Sdimstatic DecodeStatus DecodeLoadPairExclusiveInstruction(llvm::MCInst &Inst,
202249259Sdim                                                       unsigned Val,
203249259Sdim                                                       uint64_t Address,
204249259Sdim                                                       const void *Decoder);
205249259Sdim
206249259Sdimtemplate<typename SomeNamedImmMapper>
207249259Sdimstatic DecodeStatus DecodeNamedImmOperand(llvm::MCInst &Inst,
208249259Sdim                                          unsigned Val,
209249259Sdim                                          uint64_t Address,
210249259Sdim                                          const void *Decoder);
211249259Sdim
212249259Sdimstatic DecodeStatus
213249259SdimDecodeSysRegOperand(const A64SysReg::SysRegMapper &InstMapper,
214249259Sdim                    llvm::MCInst &Inst, unsigned Val,
215249259Sdim                    uint64_t Address, const void *Decoder);
216249259Sdim
217249259Sdimstatic DecodeStatus DecodeMRSOperand(llvm::MCInst &Inst,
218249259Sdim                                     unsigned Val,
219249259Sdim                                     uint64_t Address,
220249259Sdim                                     const void *Decoder);
221249259Sdim
222249259Sdimstatic DecodeStatus DecodeMSROperand(llvm::MCInst &Inst,
223249259Sdim                                     unsigned Val,
224249259Sdim                                     uint64_t Address,
225249259Sdim                                     const void *Decoder);
226249259Sdim
227249259Sdim
228249259Sdimstatic DecodeStatus DecodeSingleIndexedInstruction(llvm::MCInst &Inst,
229249259Sdim                                                   unsigned Val,
230249259Sdim                                                   uint64_t Address,
231249259Sdim                                                   const void *Decoder);
232249259Sdim
233263508Sdimstatic DecodeStatus DecodeVLDSTPostInstruction(MCInst &Inst, unsigned Val,
234263508Sdim                                               uint64_t Address,
235263508Sdim                                               const void *Decoder);
236249259Sdim
237263508Sdimstatic DecodeStatus DecodeVLDSTLanePostInstruction(MCInst &Inst, unsigned Insn,
238263508Sdim                                                   uint64_t Address,
239263508Sdim                                                   const void *Decoder);
240263508Sdim
241263508Sdimstatic DecodeStatus DecodeSHLLInstruction(MCInst &Inst, unsigned Insn,
242263508Sdim                                          uint64_t Address,
243263508Sdim                                          const void *Decoder);
244263508Sdim
245249259Sdimstatic bool Check(DecodeStatus &Out, DecodeStatus In);
246249259Sdim
247249259Sdim#include "AArch64GenDisassemblerTables.inc"
248249259Sdim#include "AArch64GenInstrInfo.inc"
249249259Sdim
250249259Sdimstatic bool Check(DecodeStatus &Out, DecodeStatus In) {
251249259Sdim  switch (In) {
252249259Sdim    case MCDisassembler::Success:
253249259Sdim      // Out stays the same.
254249259Sdim      return true;
255249259Sdim    case MCDisassembler::SoftFail:
256249259Sdim      Out = In;
257249259Sdim      return true;
258249259Sdim    case MCDisassembler::Fail:
259249259Sdim      Out = In;
260249259Sdim      return false;
261249259Sdim  }
262249259Sdim  llvm_unreachable("Invalid DecodeStatus!");
263249259Sdim}
264249259Sdim
265249259SdimDecodeStatus AArch64Disassembler::getInstruction(MCInst &MI, uint64_t &Size,
266249259Sdim                                                 const MemoryObject &Region,
267249259Sdim                                                 uint64_t Address,
268249259Sdim                                                 raw_ostream &os,
269249259Sdim                                                 raw_ostream &cs) const {
270249259Sdim  CommentStream = &cs;
271249259Sdim
272249259Sdim  uint8_t bytes[4];
273249259Sdim
274249259Sdim  // We want to read exactly 4 bytes of data.
275263508Sdim  if (Region.readBytes(Address, 4, bytes) == -1) {
276249259Sdim    Size = 0;
277249259Sdim    return MCDisassembler::Fail;
278249259Sdim  }
279249259Sdim
280249259Sdim  // Encoded as a small-endian 32-bit word in the stream.
281249259Sdim  uint32_t insn = (bytes[3] << 24) |
282249259Sdim    (bytes[2] << 16) |
283249259Sdim    (bytes[1] <<  8) |
284249259Sdim    (bytes[0] <<  0);
285249259Sdim
286249259Sdim  // Calling the auto-generated decoder function.
287249259Sdim  DecodeStatus result = decodeInstruction(DecoderTableA6432, MI, insn, Address,
288249259Sdim                                          this, STI);
289249259Sdim  if (result != MCDisassembler::Fail) {
290249259Sdim    Size = 4;
291249259Sdim    return result;
292249259Sdim  }
293249259Sdim
294249259Sdim  MI.clear();
295249259Sdim  Size = 0;
296249259Sdim  return MCDisassembler::Fail;
297249259Sdim}
298249259Sdim
299249259Sdimstatic unsigned getReg(const void *D, unsigned RC, unsigned RegNo) {
300249259Sdim  const AArch64Disassembler *Dis = static_cast<const AArch64Disassembler*>(D);
301249259Sdim  return Dis->getRegInfo()->getRegClass(RC).getRegister(RegNo);
302249259Sdim}
303249259Sdim
304249259Sdimstatic DecodeStatus DecodeGPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
305249259Sdim                                        uint64_t Address, const void *Decoder) {
306249259Sdim  if (RegNo > 31)
307249259Sdim    return MCDisassembler::Fail;
308249259Sdim
309249259Sdim  uint16_t Register = getReg(Decoder, AArch64::GPR64RegClassID, RegNo);
310249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
311249259Sdim  return MCDisassembler::Success;
312249259Sdim}
313249259Sdim
314249259Sdimstatic DecodeStatus
315249259SdimDecodeGPR64xspRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
316249259Sdim                            uint64_t Address, const void *Decoder) {
317249259Sdim  if (RegNo > 31)
318249259Sdim    return MCDisassembler::Fail;
319249259Sdim
320249259Sdim  uint16_t Register = getReg(Decoder, AArch64::GPR64xspRegClassID, RegNo);
321249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
322249259Sdim  return MCDisassembler::Success;
323249259Sdim}
324249259Sdim
325249259Sdimstatic DecodeStatus DecodeGPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
326249259Sdim                                             uint64_t Address,
327249259Sdim                                             const void *Decoder) {
328249259Sdim  if (RegNo > 31)
329249259Sdim    return MCDisassembler::Fail;
330249259Sdim
331249259Sdim  uint16_t Register = getReg(Decoder, AArch64::GPR32RegClassID, RegNo);
332249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
333249259Sdim  return MCDisassembler::Success;
334249259Sdim}
335249259Sdim
336249259Sdimstatic DecodeStatus
337249259SdimDecodeGPR32wspRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
338249259Sdim                            uint64_t Address, const void *Decoder) {
339249259Sdim  if (RegNo > 31)
340249259Sdim    return MCDisassembler::Fail;
341249259Sdim
342249259Sdim  uint16_t Register = getReg(Decoder, AArch64::GPR32wspRegClassID, RegNo);
343249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
344249259Sdim  return MCDisassembler::Success;
345249259Sdim}
346249259Sdim
347249259Sdimstatic DecodeStatus
348249259SdimDecodeFPR8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
349249259Sdim                            uint64_t Address, const void *Decoder) {
350249259Sdim  if (RegNo > 31)
351249259Sdim    return MCDisassembler::Fail;
352249259Sdim
353249259Sdim  uint16_t Register = getReg(Decoder, AArch64::FPR8RegClassID, RegNo);
354249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
355249259Sdim  return MCDisassembler::Success;
356249259Sdim}
357249259Sdim
358249259Sdimstatic DecodeStatus
359249259SdimDecodeFPR16RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
360249259Sdim                            uint64_t Address, const void *Decoder) {
361249259Sdim  if (RegNo > 31)
362249259Sdim    return MCDisassembler::Fail;
363249259Sdim
364249259Sdim  uint16_t Register = getReg(Decoder, AArch64::FPR16RegClassID, RegNo);
365249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
366249259Sdim  return MCDisassembler::Success;
367249259Sdim}
368249259Sdim
369249259Sdim
370249259Sdimstatic DecodeStatus
371249259SdimDecodeFPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
372249259Sdim                            uint64_t Address, const void *Decoder) {
373249259Sdim  if (RegNo > 31)
374249259Sdim    return MCDisassembler::Fail;
375249259Sdim
376249259Sdim  uint16_t Register = getReg(Decoder, AArch64::FPR32RegClassID, RegNo);
377249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
378249259Sdim  return MCDisassembler::Success;
379249259Sdim}
380249259Sdim
381249259Sdimstatic DecodeStatus
382249259SdimDecodeFPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
383249259Sdim                            uint64_t Address, const void *Decoder) {
384249259Sdim  if (RegNo > 31)
385249259Sdim    return MCDisassembler::Fail;
386249259Sdim
387249259Sdim  uint16_t Register = getReg(Decoder, AArch64::FPR64RegClassID, RegNo);
388249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
389249259Sdim  return MCDisassembler::Success;
390249259Sdim}
391249259Sdim
392263508Sdimstatic DecodeStatus
393263508SdimDecodeFPR64LoRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
394263508Sdim                            uint64_t Address, const void *Decoder) {
395263508Sdim  if (RegNo > 15)
396263508Sdim    return MCDisassembler::Fail;
397249259Sdim
398263508Sdim  return DecodeFPR64RegisterClass(Inst, RegNo, Address, Decoder);
399263508Sdim}
400263508Sdim
401249259Sdimstatic DecodeStatus
402249259SdimDecodeFPR128RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
403249259Sdim                            uint64_t Address, const void *Decoder) {
404249259Sdim  if (RegNo > 31)
405249259Sdim    return MCDisassembler::Fail;
406249259Sdim
407249259Sdim  uint16_t Register = getReg(Decoder, AArch64::FPR128RegClassID, RegNo);
408249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
409249259Sdim  return MCDisassembler::Success;
410249259Sdim}
411249259Sdim
412249259Sdimstatic DecodeStatus
413263508SdimDecodeFPR128LoRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
414263508Sdim                            uint64_t Address, const void *Decoder) {
415263508Sdim  if (RegNo > 15)
416263508Sdim    return MCDisassembler::Fail;
417263508Sdim
418263508Sdim  return DecodeFPR128RegisterClass(Inst, RegNo, Address, Decoder);
419263508Sdim}
420263508Sdim
421263508Sdimstatic DecodeStatus DecodeGPR64noxzrRegisterClass(llvm::MCInst &Inst,
422263508Sdim                                                  unsigned RegNo,
423263508Sdim                                                  uint64_t Address,
424263508Sdim                                                  const void *Decoder) {
425263508Sdim  if (RegNo > 30)
426263508Sdim    return MCDisassembler::Fail;
427263508Sdim
428263508Sdim  uint16_t Register = getReg(Decoder, AArch64::GPR64noxzrRegClassID, RegNo);
429263508Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
430263508Sdim  return MCDisassembler::Success;
431263508Sdim}
432263508Sdim
433263508Sdimstatic DecodeStatus DecodeRegisterClassByID(llvm::MCInst &Inst, unsigned RegNo,
434263508Sdim                                            unsigned RegID,
435263508Sdim                                            const void *Decoder) {
436249259Sdim  if (RegNo > 31)
437249259Sdim    return MCDisassembler::Fail;
438249259Sdim
439263508Sdim  uint16_t Register = getReg(Decoder, RegID, RegNo);
440249259Sdim  Inst.addOperand(MCOperand::CreateReg(Register));
441249259Sdim  return MCDisassembler::Success;
442249259Sdim}
443249259Sdim
444263508Sdimstatic DecodeStatus DecodeDPairRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
445263508Sdim                                             uint64_t Address,
446263508Sdim                                             const void *Decoder) {
447263508Sdim  return DecodeRegisterClassByID(Inst, RegNo, AArch64::DPairRegClassID,
448263508Sdim                                 Decoder);
449263508Sdim}
450263508Sdim
451263508Sdimstatic DecodeStatus DecodeQPairRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
452263508Sdim                                             uint64_t Address,
453263508Sdim                                             const void *Decoder) {
454263508Sdim  return DecodeRegisterClassByID(Inst, RegNo, AArch64::QPairRegClassID,
455263508Sdim                                 Decoder);
456263508Sdim}
457263508Sdim
458263508Sdimstatic DecodeStatus DecodeDTripleRegisterClass(llvm::MCInst &Inst,
459263508Sdim                                               unsigned RegNo, uint64_t Address,
460263508Sdim                                               const void *Decoder) {
461263508Sdim  return DecodeRegisterClassByID(Inst, RegNo, AArch64::DTripleRegClassID,
462263508Sdim                                 Decoder);
463263508Sdim}
464263508Sdim
465263508Sdimstatic DecodeStatus DecodeQTripleRegisterClass(llvm::MCInst &Inst,
466263508Sdim                                               unsigned RegNo, uint64_t Address,
467263508Sdim                                               const void *Decoder) {
468263508Sdim  return DecodeRegisterClassByID(Inst, RegNo, AArch64::QTripleRegClassID,
469263508Sdim                                 Decoder);
470263508Sdim}
471263508Sdim
472263508Sdimstatic DecodeStatus DecodeDQuadRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
473263508Sdim                                             uint64_t Address,
474263508Sdim                                             const void *Decoder) {
475263508Sdim  return DecodeRegisterClassByID(Inst, RegNo, AArch64::DQuadRegClassID,
476263508Sdim                                 Decoder);
477263508Sdim}
478263508Sdim
479263508Sdimstatic DecodeStatus DecodeQQuadRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
480263508Sdim                                             uint64_t Address,
481263508Sdim                                             const void *Decoder) {
482263508Sdim  return DecodeRegisterClassByID(Inst, RegNo, AArch64::QQuadRegClassID,
483263508Sdim                                 Decoder);
484263508Sdim}
485263508Sdim
486249259Sdimstatic DecodeStatus DecodeAddrRegExtendOperand(llvm::MCInst &Inst,
487249259Sdim                                               unsigned OptionHiS,
488249259Sdim                                               uint64_t Address,
489249259Sdim                                               const void *Decoder) {
490249259Sdim  // Option{1} must be 1. OptionHiS is made up of {Option{2}, Option{1},
491249259Sdim  // S}. Hence we want to check bit 1.
492249259Sdim  if (!(OptionHiS & 2))
493249259Sdim    return MCDisassembler::Fail;
494249259Sdim
495249259Sdim  Inst.addOperand(MCOperand::CreateImm(OptionHiS));
496249259Sdim  return MCDisassembler::Success;
497249259Sdim}
498249259Sdim
499249259Sdimstatic DecodeStatus DecodeBitfield32ImmOperand(llvm::MCInst &Inst,
500249259Sdim                                               unsigned Imm6Bits,
501249259Sdim                                               uint64_t Address,
502249259Sdim                                               const void *Decoder) {
503249259Sdim  // In the 32-bit variant, bit 6 must be zero. I.e. the immediate must be
504249259Sdim  // between 0 and 31.
505249259Sdim  if (Imm6Bits > 31)
506249259Sdim    return MCDisassembler::Fail;
507249259Sdim
508249259Sdim  Inst.addOperand(MCOperand::CreateImm(Imm6Bits));
509249259Sdim  return MCDisassembler::Success;
510249259Sdim}
511249259Sdim
512249259Sdimstatic DecodeStatus DecodeCVT32FixedPosOperand(llvm::MCInst &Inst,
513249259Sdim                                               unsigned Imm6Bits,
514249259Sdim                                               uint64_t Address,
515249259Sdim                                               const void *Decoder) {
516249259Sdim  // 1 <= Imm <= 32. Encoded as 64 - Imm so: 63 >= Encoded >= 32.
517249259Sdim  if (Imm6Bits < 32)
518249259Sdim    return MCDisassembler::Fail;
519249259Sdim
520249259Sdim  Inst.addOperand(MCOperand::CreateImm(Imm6Bits));
521249259Sdim  return MCDisassembler::Success;
522249259Sdim}
523249259Sdim
524249259Sdimstatic DecodeStatus DecodeFPZeroOperand(llvm::MCInst &Inst,
525249259Sdim                                        unsigned RmBits,
526249259Sdim                                        uint64_t Address,
527249259Sdim                                        const void *Decoder) {
528249259Sdim  // Any bits are valid in the instruction (they're architecturally ignored),
529249259Sdim  // but a code generator should insert 0.
530249259Sdim  Inst.addOperand(MCOperand::CreateImm(0));
531249259Sdim  return MCDisassembler::Success;
532249259Sdim}
533249259Sdim
534263508Sdimstatic DecodeStatus DecodeShiftRightImm8(MCInst &Inst, unsigned Val,
535263508Sdim                                         uint64_t Address,
536263508Sdim                                         const void *Decoder) {
537263508Sdim  Inst.addOperand(MCOperand::CreateImm(8 - Val));
538263508Sdim  return MCDisassembler::Success;
539263508Sdim}
540249259Sdim
541263508Sdimstatic DecodeStatus DecodeShiftRightImm16(MCInst &Inst, unsigned Val,
542263508Sdim                                          uint64_t Address,
543263508Sdim                                          const void *Decoder) {
544263508Sdim  Inst.addOperand(MCOperand::CreateImm(16 - Val));
545263508Sdim  return MCDisassembler::Success;
546263508Sdim}
547249259Sdim
548263508Sdimstatic DecodeStatus DecodeShiftRightImm32(MCInst &Inst, unsigned Val,
549263508Sdim                                          uint64_t Address,
550263508Sdim                                          const void *Decoder) {
551263508Sdim  Inst.addOperand(MCOperand::CreateImm(32 - Val));
552263508Sdim  return MCDisassembler::Success;
553263508Sdim}
554263508Sdim
555263508Sdimstatic DecodeStatus DecodeShiftRightImm64(MCInst &Inst, unsigned Val,
556263508Sdim                                          uint64_t Address,
557263508Sdim                                          const void *Decoder) {
558263508Sdim  Inst.addOperand(MCOperand::CreateImm(64 - Val));
559263508Sdim  return MCDisassembler::Success;
560263508Sdim}
561263508Sdim
562263508Sdimstatic DecodeStatus DecodeShiftLeftImm8(MCInst &Inst, unsigned Val,
563263508Sdim                                        uint64_t Address,
564263508Sdim                                        const void *Decoder) {
565263508Sdim  if (Val > 7)
566263508Sdim    return MCDisassembler::Fail;
567263508Sdim
568263508Sdim  Inst.addOperand(MCOperand::CreateImm(Val));
569263508Sdim  return MCDisassembler::Success;
570263508Sdim}
571263508Sdim
572263508Sdimstatic DecodeStatus DecodeShiftLeftImm16(MCInst &Inst, unsigned Val,
573263508Sdim                                         uint64_t Address,
574263508Sdim                                         const void *Decoder) {
575263508Sdim  if (Val > 15)
576263508Sdim    return MCDisassembler::Fail;
577263508Sdim
578263508Sdim  Inst.addOperand(MCOperand::CreateImm(Val));
579263508Sdim  return MCDisassembler::Success;
580263508Sdim}
581263508Sdim
582263508Sdimstatic DecodeStatus DecodeShiftLeftImm32(MCInst &Inst, unsigned Val,
583263508Sdim                                         uint64_t Address,
584263508Sdim                                         const void *Decoder) {
585263508Sdim  if (Val > 31)
586263508Sdim    return MCDisassembler::Fail;
587263508Sdim
588263508Sdim  Inst.addOperand(MCOperand::CreateImm(Val));
589263508Sdim  return MCDisassembler::Success;
590263508Sdim}
591263508Sdim
592263508Sdimstatic DecodeStatus DecodeShiftLeftImm64(MCInst &Inst, unsigned Val,
593263508Sdim                                         uint64_t Address,
594263508Sdim                                         const void *Decoder) {
595263508Sdim  if (Val > 63)
596263508Sdim    return MCDisassembler::Fail;
597263508Sdim
598263508Sdim  Inst.addOperand(MCOperand::CreateImm(Val));
599263508Sdim  return MCDisassembler::Success;
600263508Sdim}
601263508Sdim
602249259Sdimtemplate<int RegWidth>
603249259Sdimstatic DecodeStatus DecodeMoveWideImmOperand(llvm::MCInst &Inst,
604249259Sdim                                             unsigned FullImm,
605249259Sdim                                             uint64_t Address,
606249259Sdim                                             const void *Decoder) {
607249259Sdim  unsigned Imm16 = FullImm & 0xffff;
608249259Sdim  unsigned Shift = FullImm >> 16;
609249259Sdim
610249259Sdim  if (RegWidth == 32 && Shift > 1) return MCDisassembler::Fail;
611249259Sdim
612249259Sdim  Inst.addOperand(MCOperand::CreateImm(Imm16));
613249259Sdim  Inst.addOperand(MCOperand::CreateImm(Shift));
614249259Sdim  return MCDisassembler::Success;
615249259Sdim}
616249259Sdim
617249259Sdimtemplate<int RegWidth>
618249259Sdimstatic DecodeStatus DecodeLogicalImmOperand(llvm::MCInst &Inst,
619249259Sdim                                            unsigned Bits,
620249259Sdim                                            uint64_t Address,
621249259Sdim                                            const void *Decoder) {
622249259Sdim  uint64_t Imm;
623249259Sdim  if (!A64Imms::isLogicalImmBits(RegWidth, Bits, Imm))
624249259Sdim    return MCDisassembler::Fail;
625249259Sdim
626249259Sdim  Inst.addOperand(MCOperand::CreateImm(Bits));
627249259Sdim  return MCDisassembler::Success;
628249259Sdim}
629249259Sdim
630249259Sdim
631249259Sdimstatic DecodeStatus DecodeRegExtendOperand(llvm::MCInst &Inst,
632249259Sdim                                           unsigned ShiftAmount,
633249259Sdim                                           uint64_t Address,
634249259Sdim                                           const void *Decoder) {
635249259Sdim  // Only values 0-4 are valid for this 3-bit field
636249259Sdim  if (ShiftAmount > 4)
637249259Sdim    return MCDisassembler::Fail;
638249259Sdim
639249259Sdim  Inst.addOperand(MCOperand::CreateImm(ShiftAmount));
640249259Sdim  return MCDisassembler::Success;
641249259Sdim}
642249259Sdim
643249259Sdimstatic DecodeStatus Decode32BitShiftOperand(llvm::MCInst &Inst,
644249259Sdim                                            unsigned ShiftAmount,
645249259Sdim                                            uint64_t Address,
646249259Sdim                                            const void *Decoder) {
647249259Sdim  // Only values below 32 are valid for a 32-bit register
648249259Sdim  if (ShiftAmount > 31)
649249259Sdim    return MCDisassembler::Fail;
650249259Sdim
651249259Sdim  Inst.addOperand(MCOperand::CreateImm(ShiftAmount));
652249259Sdim  return MCDisassembler::Success;
653249259Sdim}
654249259Sdim
655249259Sdimstatic DecodeStatus DecodeBitfieldInstruction(llvm::MCInst &Inst, unsigned Insn,
656249259Sdim                                              uint64_t Address,
657249259Sdim                                              const void *Decoder) {
658249259Sdim  unsigned Rd = fieldFromInstruction(Insn, 0, 5);
659249259Sdim  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
660249259Sdim  unsigned ImmS = fieldFromInstruction(Insn, 10, 6);
661249259Sdim  unsigned ImmR = fieldFromInstruction(Insn, 16, 6);
662249259Sdim  unsigned SF = fieldFromInstruction(Insn, 31, 1);
663249259Sdim
664249259Sdim  // Undef for 0b11 just in case it occurs. Don't want the compiler to optimise
665249259Sdim  // out assertions that it thinks should never be hit.
666249259Sdim  enum OpcTypes { SBFM = 0, BFM, UBFM, Undef } Opc;
667249259Sdim  Opc = (OpcTypes)fieldFromInstruction(Insn, 29, 2);
668249259Sdim
669249259Sdim  if (!SF) {
670249259Sdim    // ImmR and ImmS must be between 0 and 31 for 32-bit instructions.
671249259Sdim    if (ImmR > 31 || ImmS > 31)
672249259Sdim      return MCDisassembler::Fail;
673249259Sdim  }
674249259Sdim
675249259Sdim  if (SF) {
676249259Sdim    DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder);
677249259Sdim    // BFM MCInsts use Rd as a source too.
678249259Sdim    if (Opc == BFM) DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder);
679249259Sdim    DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder);
680249259Sdim  } else {
681249259Sdim    DecodeGPR32RegisterClass(Inst, Rd, Address, Decoder);
682249259Sdim    // BFM MCInsts use Rd as a source too.
683249259Sdim    if (Opc == BFM) DecodeGPR32RegisterClass(Inst, Rd, Address, Decoder);
684249259Sdim    DecodeGPR32RegisterClass(Inst, Rn, Address, Decoder);
685249259Sdim  }
686249259Sdim
687249259Sdim  // ASR and LSR have more specific patterns so they won't get here:
688249259Sdim  assert(!(ImmS == 31 && !SF && Opc != BFM)
689249259Sdim         && "shift should have used auto decode");
690249259Sdim  assert(!(ImmS == 63 && SF && Opc != BFM)
691249259Sdim         && "shift should have used auto decode");
692249259Sdim
693249259Sdim  // Extension instructions similarly:
694249259Sdim  if (Opc == SBFM && ImmR == 0) {
695249259Sdim    assert((ImmS != 7 && ImmS != 15) && "extension got here");
696249259Sdim    assert((ImmS != 31 || SF == 0) && "extension got here");
697249259Sdim  } else if (Opc == UBFM && ImmR == 0) {
698249259Sdim    assert((SF != 0 || (ImmS != 7 && ImmS != 15)) && "extension got here");
699249259Sdim  }
700249259Sdim
701249259Sdim  if (Opc == UBFM) {
702249259Sdim    // It might be a LSL instruction, which actually takes the shift amount
703249259Sdim    // itself as an MCInst operand.
704249259Sdim    if (SF && (ImmS + 1) % 64 == ImmR) {
705249259Sdim      Inst.setOpcode(AArch64::LSLxxi);
706249259Sdim      Inst.addOperand(MCOperand::CreateImm(63 - ImmS));
707249259Sdim      return MCDisassembler::Success;
708249259Sdim    } else if (!SF && (ImmS + 1) % 32 == ImmR) {
709249259Sdim      Inst.setOpcode(AArch64::LSLwwi);
710249259Sdim      Inst.addOperand(MCOperand::CreateImm(31 - ImmS));
711249259Sdim      return MCDisassembler::Success;
712249259Sdim    }
713249259Sdim  }
714249259Sdim
715249259Sdim  // Otherwise it's definitely either an extract or an insert depending on which
716249259Sdim  // of ImmR or ImmS is larger.
717249259Sdim  unsigned ExtractOp, InsertOp;
718249259Sdim  switch (Opc) {
719249259Sdim  default: llvm_unreachable("unexpected instruction trying to decode bitfield");
720249259Sdim  case SBFM:
721249259Sdim    ExtractOp = SF ? AArch64::SBFXxxii : AArch64::SBFXwwii;
722249259Sdim    InsertOp = SF ? AArch64::SBFIZxxii : AArch64::SBFIZwwii;
723249259Sdim    break;
724249259Sdim  case BFM:
725249259Sdim    ExtractOp = SF ? AArch64::BFXILxxii : AArch64::BFXILwwii;
726249259Sdim    InsertOp = SF ? AArch64::BFIxxii : AArch64::BFIwwii;
727249259Sdim    break;
728249259Sdim  case UBFM:
729249259Sdim    ExtractOp = SF ? AArch64::UBFXxxii : AArch64::UBFXwwii;
730249259Sdim    InsertOp = SF ? AArch64::UBFIZxxii : AArch64::UBFIZwwii;
731249259Sdim    break;
732249259Sdim  }
733249259Sdim
734249259Sdim  // Otherwise it's a boring insert or extract
735249259Sdim  Inst.addOperand(MCOperand::CreateImm(ImmR));
736249259Sdim  Inst.addOperand(MCOperand::CreateImm(ImmS));
737249259Sdim
738249259Sdim
739249259Sdim  if (ImmS < ImmR)
740249259Sdim    Inst.setOpcode(InsertOp);
741249259Sdim  else
742249259Sdim    Inst.setOpcode(ExtractOp);
743249259Sdim
744249259Sdim  return MCDisassembler::Success;
745249259Sdim}
746249259Sdim
747249259Sdimstatic DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn,
748249259Sdim                                              uint64_t Address,
749249259Sdim                                              const void *Decoder) {
750249259Sdim  // This decoder exists to add the dummy Lane operand to the MCInst, which must
751249259Sdim  // be 1 in assembly but has no other real manifestation.
752249259Sdim  unsigned Rd = fieldFromInstruction(Insn, 0, 5);
753249259Sdim  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
754249259Sdim  unsigned IsToVec = fieldFromInstruction(Insn, 16, 1);
755249259Sdim
756249259Sdim  if (IsToVec) {
757263508Sdim    DecodeFPR128RegisterClass(Inst, Rd, Address, Decoder);
758249259Sdim    DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder);
759249259Sdim  } else {
760249259Sdim    DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder);
761263508Sdim    DecodeFPR128RegisterClass(Inst, Rn, Address, Decoder);
762249259Sdim  }
763249259Sdim
764249259Sdim  // Add the lane
765249259Sdim  Inst.addOperand(MCOperand::CreateImm(1));
766249259Sdim
767249259Sdim  return MCDisassembler::Success;
768249259Sdim}
769249259Sdim
770249259Sdim
771249259Sdimstatic DecodeStatus DecodeLDSTPairInstruction(llvm::MCInst &Inst,
772249259Sdim                                              unsigned Insn,
773249259Sdim                                              uint64_t Address,
774249259Sdim                                              const void *Decoder) {
775249259Sdim  DecodeStatus Result = MCDisassembler::Success;
776249259Sdim  unsigned Rt = fieldFromInstruction(Insn, 0, 5);
777249259Sdim  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
778249259Sdim  unsigned Rt2 = fieldFromInstruction(Insn, 10, 5);
779249259Sdim  unsigned SImm7 = fieldFromInstruction(Insn, 15, 7);
780249259Sdim  unsigned L = fieldFromInstruction(Insn, 22, 1);
781249259Sdim  unsigned V = fieldFromInstruction(Insn, 26, 1);
782249259Sdim  unsigned Opc = fieldFromInstruction(Insn, 30, 2);
783249259Sdim
784249259Sdim  // Not an official name, but it turns out that bit 23 distinguishes indexed
785249259Sdim  // from non-indexed operations.
786249259Sdim  unsigned Indexed = fieldFromInstruction(Insn, 23, 1);
787249259Sdim
788249259Sdim  if (Indexed && L == 0) {
789249259Sdim    // The MCInst for an indexed store has an out operand and 4 ins:
790249259Sdim    //    Rn_wb, Rt, Rt2, Rn, Imm
791249259Sdim    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
792249259Sdim  }
793249259Sdim
794249259Sdim  // You shouldn't load to the same register twice in an instruction...
795249259Sdim  if (L && Rt == Rt2)
796249259Sdim    Result = MCDisassembler::SoftFail;
797249259Sdim
798249259Sdim  // ... or do any operation that writes-back to a transfer register. But note
799249259Sdim  // that "stp xzr, xzr, [sp], #4" is fine because xzr and sp are different.
800249259Sdim  if (Indexed && V == 0 && Rn != 31 && (Rt == Rn || Rt2 == Rn))
801249259Sdim    Result = MCDisassembler::SoftFail;
802249259Sdim
803249259Sdim  // Exactly how we decode the MCInst's registers depends on the Opc and V
804249259Sdim  // fields of the instruction. These also obviously determine the size of the
805249259Sdim  // operation so we can fill in that information while we're at it.
806249259Sdim  if (V) {
807249259Sdim    // The instruction operates on the FP/SIMD registers
808249259Sdim    switch (Opc) {
809249259Sdim    default: return MCDisassembler::Fail;
810249259Sdim    case 0:
811249259Sdim      DecodeFPR32RegisterClass(Inst, Rt, Address, Decoder);
812249259Sdim      DecodeFPR32RegisterClass(Inst, Rt2, Address, Decoder);
813249259Sdim      break;
814249259Sdim    case 1:
815249259Sdim      DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder);
816249259Sdim      DecodeFPR64RegisterClass(Inst, Rt2, Address, Decoder);
817249259Sdim      break;
818249259Sdim    case 2:
819249259Sdim      DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder);
820249259Sdim      DecodeFPR128RegisterClass(Inst, Rt2, Address, Decoder);
821249259Sdim      break;
822249259Sdim    }
823249259Sdim  } else {
824249259Sdim    switch (Opc) {
825249259Sdim    default: return MCDisassembler::Fail;
826249259Sdim    case 0:
827249259Sdim      DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder);
828249259Sdim      DecodeGPR32RegisterClass(Inst, Rt2, Address, Decoder);
829249259Sdim      break;
830249259Sdim    case 1:
831249259Sdim      assert(L && "unexpected \"store signed\" attempt");
832249259Sdim      DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder);
833249259Sdim      DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder);
834249259Sdim      break;
835249259Sdim    case 2:
836249259Sdim      DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder);
837249259Sdim      DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder);
838249259Sdim      break;
839249259Sdim    }
840249259Sdim  }
841249259Sdim
842249259Sdim  if (Indexed && L == 1) {
843249259Sdim    // The MCInst for an indexed load has 3 out operands and an 3 ins:
844249259Sdim    //    Rt, Rt2, Rn_wb, Rt2, Rn, Imm
845249259Sdim    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
846249259Sdim  }
847249259Sdim
848249259Sdim
849249259Sdim  DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
850249259Sdim  Inst.addOperand(MCOperand::CreateImm(SImm7));
851249259Sdim
852249259Sdim  return Result;
853249259Sdim}
854249259Sdim
855249259Sdimstatic DecodeStatus DecodeLoadPairExclusiveInstruction(llvm::MCInst &Inst,
856249259Sdim                                                       uint32_t Val,
857249259Sdim                                                       uint64_t Address,
858249259Sdim                                                       const void *Decoder) {
859249259Sdim  unsigned Rt = fieldFromInstruction(Val, 0, 5);
860249259Sdim  unsigned Rn = fieldFromInstruction(Val, 5, 5);
861249259Sdim  unsigned Rt2 = fieldFromInstruction(Val, 10, 5);
862249259Sdim  unsigned MemSize = fieldFromInstruction(Val, 30, 2);
863249259Sdim
864249259Sdim  DecodeStatus S = MCDisassembler::Success;
865249259Sdim  if (Rt == Rt2) S = MCDisassembler::SoftFail;
866249259Sdim
867249259Sdim  switch (MemSize) {
868249259Sdim    case 2:
869249259Sdim      if (!Check(S, DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder)))
870249259Sdim        return MCDisassembler::Fail;
871249259Sdim      if (!Check(S, DecodeGPR32RegisterClass(Inst, Rt2, Address, Decoder)))
872249259Sdim        return MCDisassembler::Fail;
873249259Sdim      break;
874249259Sdim    case 3:
875249259Sdim      if (!Check(S, DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder)))
876249259Sdim        return MCDisassembler::Fail;
877249259Sdim      if (!Check(S, DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder)))
878249259Sdim        return MCDisassembler::Fail;
879249259Sdim      break;
880249259Sdim    default:
881249259Sdim      llvm_unreachable("Invalid MemSize in DecodeLoadPairExclusiveInstruction");
882249259Sdim  }
883249259Sdim
884249259Sdim  if (!Check(S, DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder)))
885249259Sdim    return MCDisassembler::Fail;
886249259Sdim
887249259Sdim  return S;
888249259Sdim}
889249259Sdim
890249259Sdimtemplate<typename SomeNamedImmMapper>
891249259Sdimstatic DecodeStatus DecodeNamedImmOperand(llvm::MCInst &Inst,
892249259Sdim                                          unsigned Val,
893249259Sdim                                          uint64_t Address,
894249259Sdim                                          const void *Decoder) {
895249259Sdim  SomeNamedImmMapper Mapper;
896249259Sdim  bool ValidNamed;
897249259Sdim  Mapper.toString(Val, ValidNamed);
898249259Sdim  if (ValidNamed || Mapper.validImm(Val)) {
899249259Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
900249259Sdim    return MCDisassembler::Success;
901249259Sdim  }
902249259Sdim
903249259Sdim  return MCDisassembler::Fail;
904249259Sdim}
905249259Sdim
906249259Sdimstatic DecodeStatus DecodeSysRegOperand(const A64SysReg::SysRegMapper &Mapper,
907249259Sdim                                        llvm::MCInst &Inst,
908249259Sdim                                        unsigned Val,
909249259Sdim                                        uint64_t Address,
910249259Sdim                                        const void *Decoder) {
911249259Sdim  bool ValidNamed;
912249259Sdim  Mapper.toString(Val, ValidNamed);
913249259Sdim
914249259Sdim  Inst.addOperand(MCOperand::CreateImm(Val));
915249259Sdim
916249259Sdim  return ValidNamed ? MCDisassembler::Success : MCDisassembler::Fail;
917249259Sdim}
918249259Sdim
919249259Sdimstatic DecodeStatus DecodeMRSOperand(llvm::MCInst &Inst,
920249259Sdim                                     unsigned Val,
921249259Sdim                                     uint64_t Address,
922249259Sdim                                     const void *Decoder) {
923249259Sdim  return DecodeSysRegOperand(A64SysReg::MRSMapper(), Inst, Val, Address,
924249259Sdim                             Decoder);
925249259Sdim}
926249259Sdim
927249259Sdimstatic DecodeStatus DecodeMSROperand(llvm::MCInst &Inst,
928249259Sdim                                     unsigned Val,
929249259Sdim                                     uint64_t Address,
930249259Sdim                                     const void *Decoder) {
931249259Sdim  return DecodeSysRegOperand(A64SysReg::MSRMapper(), Inst, Val, Address,
932249259Sdim                             Decoder);
933249259Sdim}
934249259Sdim
935249259Sdimstatic DecodeStatus DecodeSingleIndexedInstruction(llvm::MCInst &Inst,
936249259Sdim                                                   unsigned Insn,
937249259Sdim                                                   uint64_t Address,
938249259Sdim                                                   const void *Decoder) {
939249259Sdim  unsigned Rt = fieldFromInstruction(Insn, 0, 5);
940249259Sdim  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
941249259Sdim  unsigned Imm9 = fieldFromInstruction(Insn, 12, 9);
942249259Sdim
943249259Sdim  unsigned Opc = fieldFromInstruction(Insn, 22, 2);
944249259Sdim  unsigned V = fieldFromInstruction(Insn, 26, 1);
945249259Sdim  unsigned Size = fieldFromInstruction(Insn, 30, 2);
946249259Sdim
947249259Sdim  if (Opc == 0 || (V == 1 && Opc == 2)) {
948249259Sdim    // It's a store, the MCInst gets: Rn_wb, Rt, Rn, Imm
949249259Sdim    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
950249259Sdim  }
951249259Sdim
952249259Sdim  if (V == 0 && (Opc == 2 || Size == 3)) {
953249259Sdim    DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder);
954249259Sdim  } else if (V == 0) {
955249259Sdim    DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder);
956249259Sdim  } else if (V == 1 && (Opc & 2)) {
957249259Sdim    DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder);
958249259Sdim  } else {
959249259Sdim    switch (Size) {
960249259Sdim    case 0:
961249259Sdim      DecodeFPR8RegisterClass(Inst, Rt, Address, Decoder);
962249259Sdim      break;
963249259Sdim    case 1:
964249259Sdim      DecodeFPR16RegisterClass(Inst, Rt, Address, Decoder);
965249259Sdim      break;
966249259Sdim    case 2:
967249259Sdim      DecodeFPR32RegisterClass(Inst, Rt, Address, Decoder);
968249259Sdim      break;
969249259Sdim    case 3:
970249259Sdim      DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder);
971249259Sdim      break;
972249259Sdim    }
973249259Sdim  }
974249259Sdim
975249259Sdim  if (Opc != 0 && (V != 1 || Opc != 2)) {
976249259Sdim    // It's a load, the MCInst gets: Rt, Rn_wb, Rn, Imm
977249259Sdim    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
978249259Sdim  }
979249259Sdim
980249259Sdim  DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
981249259Sdim
982249259Sdim  Inst.addOperand(MCOperand::CreateImm(Imm9));
983249259Sdim
984249259Sdim  // N.b. The official documentation says undpredictable if Rt == Rn, but this
985249259Sdim  // takes place at the architectural rather than encoding level:
986249259Sdim  //
987249259Sdim  // "STR xzr, [sp], #4" is perfectly valid.
988249259Sdim  if (V == 0 && Rt == Rn && Rn != 31)
989249259Sdim    return MCDisassembler::SoftFail;
990249259Sdim  else
991249259Sdim    return MCDisassembler::Success;
992249259Sdim}
993249259Sdim
994249259Sdimstatic MCDisassembler *createAArch64Disassembler(const Target &T,
995249259Sdim                                                 const MCSubtargetInfo &STI) {
996249259Sdim  return new AArch64Disassembler(STI, T.createMCRegInfo(""));
997249259Sdim}
998249259Sdim
999249259Sdimextern "C" void LLVMInitializeAArch64Disassembler() {
1000249259Sdim  TargetRegistry::RegisterMCDisassembler(TheAArch64Target,
1001249259Sdim                                         createAArch64Disassembler);
1002249259Sdim}
1003249259Sdim
1004263508Sdimtemplate <A64SE::ShiftExtSpecifiers Ext, bool IsHalf>
1005263508Sdimstatic DecodeStatus
1006263508SdimDecodeNeonMovImmShiftOperand(llvm::MCInst &Inst, unsigned ShiftAmount,
1007263508Sdim                             uint64_t Address, const void *Decoder) {
1008263508Sdim  bool IsLSL = false;
1009263508Sdim  if (Ext == A64SE::LSL)
1010263508Sdim    IsLSL = true;
1011263508Sdim  else if (Ext != A64SE::MSL)
1012263508Sdim    return MCDisassembler::Fail;
1013249259Sdim
1014263508Sdim  // MSL and LSLH accepts encoded shift amount 0 or 1.
1015263508Sdim  if ((!IsLSL || (IsLSL && IsHalf)) && ShiftAmount != 0 && ShiftAmount != 1)
1016263508Sdim    return MCDisassembler::Fail;
1017263508Sdim
1018263508Sdim  // LSL  accepts encoded shift amount 0, 1, 2 or 3.
1019263508Sdim  if (IsLSL && ShiftAmount > 3)
1020263508Sdim    return MCDisassembler::Fail;
1021263508Sdim
1022263508Sdim  Inst.addOperand(MCOperand::CreateImm(ShiftAmount));
1023263508Sdim  return MCDisassembler::Success;
1024263508Sdim}
1025263508Sdim
1026263508Sdim// Decode post-index vector load/store instructions.
1027263508Sdim// This is necessary as we need to decode Rm: if Rm == 0b11111, the last
1028263508Sdim// operand is an immediate equal the the length of vector list in bytes,
1029263508Sdim// or Rm is decoded to a GPR64noxzr register.
1030263508Sdimstatic DecodeStatus DecodeVLDSTPostInstruction(MCInst &Inst, unsigned Insn,
1031263508Sdim                                               uint64_t Address,
1032263508Sdim                                               const void *Decoder) {
1033263508Sdim  unsigned Rt = fieldFromInstruction(Insn, 0, 5);
1034263508Sdim  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
1035263508Sdim  unsigned Rm = fieldFromInstruction(Insn, 16, 5);
1036263508Sdim  unsigned Opcode = fieldFromInstruction(Insn, 12, 4);
1037263508Sdim  unsigned IsLoad = fieldFromInstruction(Insn, 22, 1);
1038263508Sdim  // 0 for 64bit vector list, 1 for 128bit vector list
1039263508Sdim  unsigned Is128BitVec = fieldFromInstruction(Insn, 30, 1);
1040263508Sdim
1041263508Sdim  unsigned NumVecs;
1042263508Sdim  switch (Opcode) {
1043263508Sdim  case 0: // ld4/st4
1044263508Sdim  case 2: // ld1/st1 with 4 vectors
1045263508Sdim    NumVecs = 4; break;
1046263508Sdim  case 4: // ld3/st3
1047263508Sdim  case 6: // ld1/st1 with 3 vectors
1048263508Sdim    NumVecs = 3; break;
1049263508Sdim  case 7: // ld1/st1 with 1 vector
1050263508Sdim    NumVecs = 1; break;
1051263508Sdim  case 8:  // ld2/st2
1052263508Sdim  case 10: // ld1/st1 with 2 vectors
1053263508Sdim    NumVecs = 2; break;
1054263508Sdim  default:
1055263508Sdim    llvm_unreachable("Invalid opcode for post-index load/store instructions");
1056263508Sdim  }
1057263508Sdim
1058263508Sdim  // Decode vector list of 1/2/3/4 vectors for load instructions.
1059263508Sdim  if (IsLoad) {
1060263508Sdim    switch (NumVecs) {
1061263508Sdim    case 1:
1062263508Sdim      Is128BitVec ? DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder)
1063263508Sdim                  : DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder);
1064263508Sdim      break;
1065263508Sdim    case 2:
1066263508Sdim      Is128BitVec ? DecodeQPairRegisterClass(Inst, Rt, Address, Decoder)
1067263508Sdim                  : DecodeDPairRegisterClass(Inst, Rt, Address, Decoder);
1068263508Sdim      break;
1069263508Sdim    case 3:
1070263508Sdim      Is128BitVec ? DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder)
1071263508Sdim                  : DecodeDTripleRegisterClass(Inst, Rt, Address, Decoder);
1072263508Sdim      break;
1073263508Sdim    case 4:
1074263508Sdim      Is128BitVec ? DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder)
1075263508Sdim                  : DecodeDQuadRegisterClass(Inst, Rt, Address, Decoder);
1076263508Sdim      break;
1077263508Sdim    }
1078263508Sdim  }
1079263508Sdim
1080263508Sdim  // Decode write back register, which is equal to Rn.
1081263508Sdim  DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
1082263508Sdim  DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
1083263508Sdim
1084263508Sdim  if (Rm == 31) // If Rm is 0x11111, add the vector list length in byte
1085263508Sdim    Inst.addOperand(MCOperand::CreateImm(NumVecs * (Is128BitVec ? 16 : 8)));
1086263508Sdim  else // Decode Rm
1087263508Sdim    DecodeGPR64noxzrRegisterClass(Inst, Rm, Address, Decoder);
1088263508Sdim
1089263508Sdim  // Decode vector list of 1/2/3/4 vectors for load instructions.
1090263508Sdim  if (!IsLoad) {
1091263508Sdim    switch (NumVecs) {
1092263508Sdim    case 1:
1093263508Sdim      Is128BitVec ? DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder)
1094263508Sdim                  : DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder);
1095263508Sdim      break;
1096263508Sdim    case 2:
1097263508Sdim      Is128BitVec ? DecodeQPairRegisterClass(Inst, Rt, Address, Decoder)
1098263508Sdim                  : DecodeDPairRegisterClass(Inst, Rt, Address, Decoder);
1099263508Sdim      break;
1100263508Sdim    case 3:
1101263508Sdim      Is128BitVec ? DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder)
1102263508Sdim                  : DecodeDTripleRegisterClass(Inst, Rt, Address, Decoder);
1103263508Sdim      break;
1104263508Sdim    case 4:
1105263508Sdim      Is128BitVec ? DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder)
1106263508Sdim                  : DecodeDQuadRegisterClass(Inst, Rt, Address, Decoder);
1107263508Sdim      break;
1108263508Sdim    }
1109263508Sdim  }
1110263508Sdim
1111263508Sdim  return MCDisassembler::Success;
1112263508Sdim}
1113263508Sdim
1114263508Sdim// Decode post-index vector load/store lane instructions.
1115263508Sdim// This is necessary as we need to decode Rm: if Rm == 0b11111, the last
1116263508Sdim// operand is an immediate equal the the length of the changed bytes,
1117263508Sdim// or Rm is decoded to a GPR64noxzr register.
1118263508Sdimstatic DecodeStatus DecodeVLDSTLanePostInstruction(MCInst &Inst, unsigned Insn,
1119263508Sdim                                                   uint64_t Address,
1120263508Sdim                                                   const void *Decoder) {
1121263508Sdim  bool Is64bitVec = false;
1122263508Sdim  bool IsLoadDup = false;
1123263508Sdim  bool IsLoad = false;
1124263508Sdim  // The total number of bytes transferred.
1125263508Sdim  // TransferBytes = NumVecs * OneLaneBytes
1126263508Sdim  unsigned TransferBytes = 0;
1127263508Sdim  unsigned NumVecs = 0;
1128263508Sdim  unsigned Opc = Inst.getOpcode();
1129263508Sdim  switch (Opc) {
1130263508Sdim  case AArch64::LD1R_WB_8B_fixed: case AArch64::LD1R_WB_8B_register:
1131263508Sdim  case AArch64::LD1R_WB_4H_fixed: case AArch64::LD1R_WB_4H_register:
1132263508Sdim  case AArch64::LD1R_WB_2S_fixed: case AArch64::LD1R_WB_2S_register:
1133263508Sdim  case AArch64::LD1R_WB_1D_fixed: case AArch64::LD1R_WB_1D_register: {
1134263508Sdim    switch (Opc) {
1135263508Sdim    case AArch64::LD1R_WB_8B_fixed: case AArch64::LD1R_WB_8B_register:
1136263508Sdim      TransferBytes = 1; break;
1137263508Sdim    case AArch64::LD1R_WB_4H_fixed: case AArch64::LD1R_WB_4H_register:
1138263508Sdim      TransferBytes = 2; break;
1139263508Sdim    case AArch64::LD1R_WB_2S_fixed: case AArch64::LD1R_WB_2S_register:
1140263508Sdim      TransferBytes = 4; break;
1141263508Sdim    case AArch64::LD1R_WB_1D_fixed: case AArch64::LD1R_WB_1D_register:
1142263508Sdim      TransferBytes = 8; break;
1143263508Sdim    }
1144263508Sdim    Is64bitVec = true;
1145263508Sdim    IsLoadDup = true;
1146263508Sdim    NumVecs = 1;
1147263508Sdim    break;
1148263508Sdim  }
1149263508Sdim
1150263508Sdim  case AArch64::LD1R_WB_16B_fixed: case AArch64::LD1R_WB_16B_register:
1151263508Sdim  case AArch64::LD1R_WB_8H_fixed: case AArch64::LD1R_WB_8H_register:
1152263508Sdim  case AArch64::LD1R_WB_4S_fixed: case AArch64::LD1R_WB_4S_register:
1153263508Sdim  case AArch64::LD1R_WB_2D_fixed: case AArch64::LD1R_WB_2D_register: {
1154263508Sdim    switch (Opc) {
1155263508Sdim    case AArch64::LD1R_WB_16B_fixed: case AArch64::LD1R_WB_16B_register:
1156263508Sdim      TransferBytes = 1; break;
1157263508Sdim    case AArch64::LD1R_WB_8H_fixed: case AArch64::LD1R_WB_8H_register:
1158263508Sdim      TransferBytes = 2; break;
1159263508Sdim    case AArch64::LD1R_WB_4S_fixed: case AArch64::LD1R_WB_4S_register:
1160263508Sdim      TransferBytes = 4; break;
1161263508Sdim    case AArch64::LD1R_WB_2D_fixed: case AArch64::LD1R_WB_2D_register:
1162263508Sdim      TransferBytes = 8; break;
1163263508Sdim    }
1164263508Sdim    IsLoadDup = true;
1165263508Sdim    NumVecs = 1;
1166263508Sdim    break;
1167263508Sdim  }
1168263508Sdim
1169263508Sdim  case AArch64::LD2R_WB_8B_fixed: case AArch64::LD2R_WB_8B_register:
1170263508Sdim  case AArch64::LD2R_WB_4H_fixed: case AArch64::LD2R_WB_4H_register:
1171263508Sdim  case AArch64::LD2R_WB_2S_fixed: case AArch64::LD2R_WB_2S_register:
1172263508Sdim  case AArch64::LD2R_WB_1D_fixed: case AArch64::LD2R_WB_1D_register: {
1173263508Sdim    switch (Opc) {
1174263508Sdim    case AArch64::LD2R_WB_8B_fixed: case AArch64::LD2R_WB_8B_register:
1175263508Sdim      TransferBytes = 2; break;
1176263508Sdim    case AArch64::LD2R_WB_4H_fixed: case AArch64::LD2R_WB_4H_register:
1177263508Sdim      TransferBytes = 4; break;
1178263508Sdim    case AArch64::LD2R_WB_2S_fixed: case AArch64::LD2R_WB_2S_register:
1179263508Sdim      TransferBytes = 8; break;
1180263508Sdim    case AArch64::LD2R_WB_1D_fixed: case AArch64::LD2R_WB_1D_register:
1181263508Sdim      TransferBytes = 16; break;
1182263508Sdim    }
1183263508Sdim    Is64bitVec = true;
1184263508Sdim    IsLoadDup = true;
1185263508Sdim    NumVecs = 2;
1186263508Sdim    break;
1187263508Sdim  }
1188263508Sdim
1189263508Sdim  case AArch64::LD2R_WB_16B_fixed: case AArch64::LD2R_WB_16B_register:
1190263508Sdim  case AArch64::LD2R_WB_8H_fixed: case AArch64::LD2R_WB_8H_register:
1191263508Sdim  case AArch64::LD2R_WB_4S_fixed: case AArch64::LD2R_WB_4S_register:
1192263508Sdim  case AArch64::LD2R_WB_2D_fixed: case AArch64::LD2R_WB_2D_register: {
1193263508Sdim    switch (Opc) {
1194263508Sdim    case AArch64::LD2R_WB_16B_fixed: case AArch64::LD2R_WB_16B_register:
1195263508Sdim      TransferBytes = 2; break;
1196263508Sdim    case AArch64::LD2R_WB_8H_fixed: case AArch64::LD2R_WB_8H_register:
1197263508Sdim      TransferBytes = 4; break;
1198263508Sdim    case AArch64::LD2R_WB_4S_fixed: case AArch64::LD2R_WB_4S_register:
1199263508Sdim      TransferBytes = 8; break;
1200263508Sdim    case AArch64::LD2R_WB_2D_fixed: case AArch64::LD2R_WB_2D_register:
1201263508Sdim      TransferBytes = 16; break;
1202263508Sdim    }
1203263508Sdim    IsLoadDup = true;
1204263508Sdim    NumVecs = 2;
1205263508Sdim    break;
1206263508Sdim  }
1207263508Sdim
1208263508Sdim  case AArch64::LD3R_WB_8B_fixed: case AArch64::LD3R_WB_8B_register:
1209263508Sdim  case AArch64::LD3R_WB_4H_fixed: case AArch64::LD3R_WB_4H_register:
1210263508Sdim  case AArch64::LD3R_WB_2S_fixed: case AArch64::LD3R_WB_2S_register:
1211263508Sdim  case AArch64::LD3R_WB_1D_fixed: case AArch64::LD3R_WB_1D_register: {
1212263508Sdim    switch (Opc) {
1213263508Sdim    case AArch64::LD3R_WB_8B_fixed: case AArch64::LD3R_WB_8B_register:
1214263508Sdim      TransferBytes = 3; break;
1215263508Sdim    case AArch64::LD3R_WB_4H_fixed: case AArch64::LD3R_WB_4H_register:
1216263508Sdim      TransferBytes = 6; break;
1217263508Sdim    case AArch64::LD3R_WB_2S_fixed: case AArch64::LD3R_WB_2S_register:
1218263508Sdim      TransferBytes = 12; break;
1219263508Sdim    case AArch64::LD3R_WB_1D_fixed: case AArch64::LD3R_WB_1D_register:
1220263508Sdim      TransferBytes = 24; break;
1221263508Sdim    }
1222263508Sdim    Is64bitVec = true;
1223263508Sdim    IsLoadDup = true;
1224263508Sdim    NumVecs = 3;
1225263508Sdim    break;
1226263508Sdim  }
1227263508Sdim
1228263508Sdim  case AArch64::LD3R_WB_16B_fixed: case AArch64::LD3R_WB_16B_register:
1229263508Sdim  case AArch64::LD3R_WB_4S_fixed: case AArch64::LD3R_WB_8H_register:
1230263508Sdim  case AArch64::LD3R_WB_8H_fixed: case AArch64::LD3R_WB_4S_register:
1231263508Sdim  case AArch64::LD3R_WB_2D_fixed: case AArch64::LD3R_WB_2D_register: {
1232263508Sdim    switch (Opc) {
1233263508Sdim    case AArch64::LD3R_WB_16B_fixed: case AArch64::LD3R_WB_16B_register:
1234263508Sdim      TransferBytes = 3; break;
1235263508Sdim    case AArch64::LD3R_WB_8H_fixed: case AArch64::LD3R_WB_8H_register:
1236263508Sdim      TransferBytes = 6; break;
1237263508Sdim    case AArch64::LD3R_WB_4S_fixed: case AArch64::LD3R_WB_4S_register:
1238263508Sdim      TransferBytes = 12; break;
1239263508Sdim    case AArch64::LD3R_WB_2D_fixed: case AArch64::LD3R_WB_2D_register:
1240263508Sdim      TransferBytes = 24; break;
1241263508Sdim    }
1242263508Sdim    IsLoadDup = true;
1243263508Sdim    NumVecs = 3;
1244263508Sdim    break;
1245263508Sdim  }
1246263508Sdim
1247263508Sdim  case AArch64::LD4R_WB_8B_fixed: case AArch64::LD4R_WB_8B_register:
1248263508Sdim  case AArch64::LD4R_WB_4H_fixed: case AArch64::LD4R_WB_4H_register:
1249263508Sdim  case AArch64::LD4R_WB_2S_fixed: case AArch64::LD4R_WB_2S_register:
1250263508Sdim  case AArch64::LD4R_WB_1D_fixed: case AArch64::LD4R_WB_1D_register: {
1251263508Sdim    switch (Opc) {
1252263508Sdim    case AArch64::LD4R_WB_8B_fixed: case AArch64::LD4R_WB_8B_register:
1253263508Sdim      TransferBytes = 4; break;
1254263508Sdim    case AArch64::LD4R_WB_4H_fixed: case AArch64::LD4R_WB_4H_register:
1255263508Sdim      TransferBytes = 8; break;
1256263508Sdim    case AArch64::LD4R_WB_2S_fixed: case AArch64::LD4R_WB_2S_register:
1257263508Sdim      TransferBytes = 16; break;
1258263508Sdim    case AArch64::LD4R_WB_1D_fixed: case AArch64::LD4R_WB_1D_register:
1259263508Sdim      TransferBytes = 32; break;
1260263508Sdim    }
1261263508Sdim    Is64bitVec = true;
1262263508Sdim    IsLoadDup = true;
1263263508Sdim    NumVecs = 4;
1264263508Sdim    break;
1265263508Sdim  }
1266263508Sdim
1267263508Sdim  case AArch64::LD4R_WB_16B_fixed: case AArch64::LD4R_WB_16B_register:
1268263508Sdim  case AArch64::LD4R_WB_4S_fixed: case AArch64::LD4R_WB_8H_register:
1269263508Sdim  case AArch64::LD4R_WB_8H_fixed: case AArch64::LD4R_WB_4S_register:
1270263508Sdim  case AArch64::LD4R_WB_2D_fixed: case AArch64::LD4R_WB_2D_register: {
1271263508Sdim    switch (Opc) {
1272263508Sdim    case AArch64::LD4R_WB_16B_fixed: case AArch64::LD4R_WB_16B_register:
1273263508Sdim      TransferBytes = 4; break;
1274263508Sdim    case AArch64::LD4R_WB_8H_fixed: case AArch64::LD4R_WB_8H_register:
1275263508Sdim      TransferBytes = 8; break;
1276263508Sdim    case AArch64::LD4R_WB_4S_fixed: case AArch64::LD4R_WB_4S_register:
1277263508Sdim      TransferBytes = 16; break;
1278263508Sdim    case AArch64::LD4R_WB_2D_fixed: case AArch64::LD4R_WB_2D_register:
1279263508Sdim      TransferBytes = 32; break;
1280263508Sdim    }
1281263508Sdim    IsLoadDup = true;
1282263508Sdim    NumVecs = 4;
1283263508Sdim    break;
1284263508Sdim  }
1285263508Sdim
1286263508Sdim  case AArch64::LD1LN_WB_B_fixed: case AArch64::LD1LN_WB_B_register:
1287263508Sdim  case AArch64::LD1LN_WB_H_fixed: case AArch64::LD1LN_WB_H_register:
1288263508Sdim  case AArch64::LD1LN_WB_S_fixed: case AArch64::LD1LN_WB_S_register:
1289263508Sdim  case AArch64::LD1LN_WB_D_fixed: case AArch64::LD1LN_WB_D_register: {
1290263508Sdim    switch (Opc) {
1291263508Sdim    case AArch64::LD1LN_WB_B_fixed: case AArch64::LD1LN_WB_B_register:
1292263508Sdim      TransferBytes = 1; break;
1293263508Sdim    case AArch64::LD1LN_WB_H_fixed: case AArch64::LD1LN_WB_H_register:
1294263508Sdim      TransferBytes = 2; break;
1295263508Sdim    case AArch64::LD1LN_WB_S_fixed: case AArch64::LD1LN_WB_S_register:
1296263508Sdim      TransferBytes = 4; break;
1297263508Sdim    case AArch64::LD1LN_WB_D_fixed: case AArch64::LD1LN_WB_D_register:
1298263508Sdim      TransferBytes = 8; break;
1299263508Sdim    }
1300263508Sdim    IsLoad = true;
1301263508Sdim    NumVecs = 1;
1302263508Sdim    break;
1303263508Sdim  }
1304263508Sdim
1305263508Sdim  case AArch64::LD2LN_WB_B_fixed: case AArch64::LD2LN_WB_B_register:
1306263508Sdim  case AArch64::LD2LN_WB_H_fixed: case AArch64::LD2LN_WB_H_register:
1307263508Sdim  case AArch64::LD2LN_WB_S_fixed: case AArch64::LD2LN_WB_S_register:
1308263508Sdim  case AArch64::LD2LN_WB_D_fixed: case AArch64::LD2LN_WB_D_register: {
1309263508Sdim    switch (Opc) {
1310263508Sdim    case AArch64::LD2LN_WB_B_fixed: case AArch64::LD2LN_WB_B_register:
1311263508Sdim      TransferBytes = 2; break;
1312263508Sdim    case AArch64::LD2LN_WB_H_fixed: case AArch64::LD2LN_WB_H_register:
1313263508Sdim      TransferBytes = 4; break;
1314263508Sdim    case AArch64::LD2LN_WB_S_fixed: case AArch64::LD2LN_WB_S_register:
1315263508Sdim      TransferBytes = 8; break;
1316263508Sdim    case AArch64::LD2LN_WB_D_fixed: case AArch64::LD2LN_WB_D_register:
1317263508Sdim      TransferBytes = 16; break;
1318263508Sdim    }
1319263508Sdim    IsLoad = true;
1320263508Sdim    NumVecs = 2;
1321263508Sdim    break;
1322263508Sdim  }
1323263508Sdim
1324263508Sdim  case AArch64::LD3LN_WB_B_fixed: case AArch64::LD3LN_WB_B_register:
1325263508Sdim  case AArch64::LD3LN_WB_H_fixed: case AArch64::LD3LN_WB_H_register:
1326263508Sdim  case AArch64::LD3LN_WB_S_fixed: case AArch64::LD3LN_WB_S_register:
1327263508Sdim  case AArch64::LD3LN_WB_D_fixed: case AArch64::LD3LN_WB_D_register: {
1328263508Sdim    switch (Opc) {
1329263508Sdim    case AArch64::LD3LN_WB_B_fixed: case AArch64::LD3LN_WB_B_register:
1330263508Sdim      TransferBytes = 3; break;
1331263508Sdim    case AArch64::LD3LN_WB_H_fixed: case AArch64::LD3LN_WB_H_register:
1332263508Sdim      TransferBytes = 6; break;
1333263508Sdim    case AArch64::LD3LN_WB_S_fixed: case AArch64::LD3LN_WB_S_register:
1334263508Sdim      TransferBytes = 12; break;
1335263508Sdim    case AArch64::LD3LN_WB_D_fixed: case AArch64::LD3LN_WB_D_register:
1336263508Sdim      TransferBytes = 24; break;
1337263508Sdim    }
1338263508Sdim    IsLoad = true;
1339263508Sdim    NumVecs = 3;
1340263508Sdim    break;
1341263508Sdim  }
1342263508Sdim
1343263508Sdim  case AArch64::LD4LN_WB_B_fixed: case AArch64::LD4LN_WB_B_register:
1344263508Sdim  case AArch64::LD4LN_WB_H_fixed: case AArch64::LD4LN_WB_H_register:
1345263508Sdim  case AArch64::LD4LN_WB_S_fixed: case AArch64::LD4LN_WB_S_register:
1346263508Sdim  case AArch64::LD4LN_WB_D_fixed: case AArch64::LD4LN_WB_D_register: {
1347263508Sdim    switch (Opc) {
1348263508Sdim    case AArch64::LD4LN_WB_B_fixed: case AArch64::LD4LN_WB_B_register:
1349263508Sdim      TransferBytes = 4; break;
1350263508Sdim    case AArch64::LD4LN_WB_H_fixed: case AArch64::LD4LN_WB_H_register:
1351263508Sdim      TransferBytes = 8; break;
1352263508Sdim    case AArch64::LD4LN_WB_S_fixed: case AArch64::LD4LN_WB_S_register:
1353263508Sdim      TransferBytes = 16; break;
1354263508Sdim    case AArch64::LD4LN_WB_D_fixed: case AArch64::LD4LN_WB_D_register:
1355263508Sdim      TransferBytes = 32; break;
1356263508Sdim    }
1357263508Sdim    IsLoad = true;
1358263508Sdim    NumVecs = 4;
1359263508Sdim    break;
1360263508Sdim  }
1361263508Sdim
1362263508Sdim  case AArch64::ST1LN_WB_B_fixed: case AArch64::ST1LN_WB_B_register:
1363263508Sdim  case AArch64::ST1LN_WB_H_fixed: case AArch64::ST1LN_WB_H_register:
1364263508Sdim  case AArch64::ST1LN_WB_S_fixed: case AArch64::ST1LN_WB_S_register:
1365263508Sdim  case AArch64::ST1LN_WB_D_fixed: case AArch64::ST1LN_WB_D_register: {
1366263508Sdim    switch (Opc) {
1367263508Sdim    case AArch64::ST1LN_WB_B_fixed: case AArch64::ST1LN_WB_B_register:
1368263508Sdim      TransferBytes = 1; break;
1369263508Sdim    case AArch64::ST1LN_WB_H_fixed: case AArch64::ST1LN_WB_H_register:
1370263508Sdim      TransferBytes = 2; break;
1371263508Sdim    case AArch64::ST1LN_WB_S_fixed: case AArch64::ST1LN_WB_S_register:
1372263508Sdim      TransferBytes = 4; break;
1373263508Sdim    case AArch64::ST1LN_WB_D_fixed: case AArch64::ST1LN_WB_D_register:
1374263508Sdim      TransferBytes = 8; break;
1375263508Sdim    }
1376263508Sdim    NumVecs = 1;
1377263508Sdim    break;
1378263508Sdim  }
1379263508Sdim
1380263508Sdim  case AArch64::ST2LN_WB_B_fixed: case AArch64::ST2LN_WB_B_register:
1381263508Sdim  case AArch64::ST2LN_WB_H_fixed: case AArch64::ST2LN_WB_H_register:
1382263508Sdim  case AArch64::ST2LN_WB_S_fixed: case AArch64::ST2LN_WB_S_register:
1383263508Sdim  case AArch64::ST2LN_WB_D_fixed: case AArch64::ST2LN_WB_D_register: {
1384263508Sdim    switch (Opc) {
1385263508Sdim    case AArch64::ST2LN_WB_B_fixed: case AArch64::ST2LN_WB_B_register:
1386263508Sdim      TransferBytes = 2; break;
1387263508Sdim    case AArch64::ST2LN_WB_H_fixed: case AArch64::ST2LN_WB_H_register:
1388263508Sdim      TransferBytes = 4; break;
1389263508Sdim    case AArch64::ST2LN_WB_S_fixed: case AArch64::ST2LN_WB_S_register:
1390263508Sdim      TransferBytes = 8; break;
1391263508Sdim    case AArch64::ST2LN_WB_D_fixed: case AArch64::ST2LN_WB_D_register:
1392263508Sdim      TransferBytes = 16; break;
1393263508Sdim    }
1394263508Sdim    NumVecs = 2;
1395263508Sdim    break;
1396263508Sdim  }
1397263508Sdim
1398263508Sdim  case AArch64::ST3LN_WB_B_fixed: case AArch64::ST3LN_WB_B_register:
1399263508Sdim  case AArch64::ST3LN_WB_H_fixed: case AArch64::ST3LN_WB_H_register:
1400263508Sdim  case AArch64::ST3LN_WB_S_fixed: case AArch64::ST3LN_WB_S_register:
1401263508Sdim  case AArch64::ST3LN_WB_D_fixed: case AArch64::ST3LN_WB_D_register: {
1402263508Sdim    switch (Opc) {
1403263508Sdim    case AArch64::ST3LN_WB_B_fixed: case AArch64::ST3LN_WB_B_register:
1404263508Sdim      TransferBytes = 3; break;
1405263508Sdim    case AArch64::ST3LN_WB_H_fixed: case AArch64::ST3LN_WB_H_register:
1406263508Sdim      TransferBytes = 6; break;
1407263508Sdim    case AArch64::ST3LN_WB_S_fixed: case AArch64::ST3LN_WB_S_register:
1408263508Sdim      TransferBytes = 12; break;
1409263508Sdim    case AArch64::ST3LN_WB_D_fixed: case AArch64::ST3LN_WB_D_register:
1410263508Sdim      TransferBytes = 24; break;
1411263508Sdim    }
1412263508Sdim    NumVecs = 3;
1413263508Sdim    break;
1414263508Sdim  }
1415263508Sdim
1416263508Sdim  case AArch64::ST4LN_WB_B_fixed: case AArch64::ST4LN_WB_B_register:
1417263508Sdim  case AArch64::ST4LN_WB_H_fixed: case AArch64::ST4LN_WB_H_register:
1418263508Sdim  case AArch64::ST4LN_WB_S_fixed: case AArch64::ST4LN_WB_S_register:
1419263508Sdim  case AArch64::ST4LN_WB_D_fixed: case AArch64::ST4LN_WB_D_register: {
1420263508Sdim    switch (Opc) {
1421263508Sdim    case AArch64::ST4LN_WB_B_fixed: case AArch64::ST4LN_WB_B_register:
1422263508Sdim      TransferBytes = 4; break;
1423263508Sdim    case AArch64::ST4LN_WB_H_fixed: case AArch64::ST4LN_WB_H_register:
1424263508Sdim      TransferBytes = 8; break;
1425263508Sdim    case AArch64::ST4LN_WB_S_fixed: case AArch64::ST4LN_WB_S_register:
1426263508Sdim      TransferBytes = 16; break;
1427263508Sdim    case AArch64::ST4LN_WB_D_fixed: case AArch64::ST4LN_WB_D_register:
1428263508Sdim      TransferBytes = 32; break;
1429263508Sdim    }
1430263508Sdim    NumVecs = 4;
1431263508Sdim    break;
1432263508Sdim  }
1433263508Sdim
1434263508Sdim  default:
1435263508Sdim    return MCDisassembler::Fail;
1436263508Sdim  } // End of switch (Opc)
1437263508Sdim
1438263508Sdim  unsigned Rt = fieldFromInstruction(Insn, 0, 5);
1439263508Sdim  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
1440263508Sdim  unsigned Rm = fieldFromInstruction(Insn, 16, 5);
1441263508Sdim
1442263508Sdim  // Decode post-index of load duplicate lane
1443263508Sdim  if (IsLoadDup) {
1444263508Sdim    switch (NumVecs) {
1445263508Sdim    case 1:
1446263508Sdim      Is64bitVec ? DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder)
1447263508Sdim                 : DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder);
1448263508Sdim      break;
1449263508Sdim    case 2:
1450263508Sdim      Is64bitVec ? DecodeDPairRegisterClass(Inst, Rt, Address, Decoder)
1451263508Sdim                 : DecodeQPairRegisterClass(Inst, Rt, Address, Decoder);
1452263508Sdim      break;
1453263508Sdim    case 3:
1454263508Sdim      Is64bitVec ? DecodeDTripleRegisterClass(Inst, Rt, Address, Decoder)
1455263508Sdim                 : DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder);
1456263508Sdim      break;
1457263508Sdim    case 4:
1458263508Sdim      Is64bitVec ? DecodeDQuadRegisterClass(Inst, Rt, Address, Decoder)
1459263508Sdim                 : DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder);
1460263508Sdim    }
1461263508Sdim
1462263508Sdim    // Decode write back register, which is equal to Rn.
1463263508Sdim    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
1464263508Sdim    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
1465263508Sdim
1466263508Sdim    if (Rm == 31) // If Rm is 0x11111, add the number of transferred bytes
1467263508Sdim      Inst.addOperand(MCOperand::CreateImm(TransferBytes));
1468263508Sdim    else // Decode Rm
1469263508Sdim      DecodeGPR64noxzrRegisterClass(Inst, Rm, Address, Decoder);
1470263508Sdim
1471263508Sdim    return MCDisassembler::Success;
1472263508Sdim  }
1473263508Sdim
1474263508Sdim  // Decode post-index of load/store lane
1475263508Sdim  // Loads have a vector list as output.
1476263508Sdim  if (IsLoad) {
1477263508Sdim    switch (NumVecs) {
1478263508Sdim    case 1:
1479263508Sdim      DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder);
1480263508Sdim      break;
1481263508Sdim    case 2:
1482263508Sdim      DecodeQPairRegisterClass(Inst, Rt, Address, Decoder);
1483263508Sdim      break;
1484263508Sdim    case 3:
1485263508Sdim      DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder);
1486263508Sdim      break;
1487263508Sdim    case 4:
1488263508Sdim      DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder);
1489263508Sdim    }
1490263508Sdim  }
1491263508Sdim
1492263508Sdim  // Decode write back register, which is equal to Rn.
1493263508Sdim  DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
1494263508Sdim  DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
1495263508Sdim
1496263508Sdim  if (Rm == 31) // If Rm is 0x11111, add the number of transferred bytes
1497263508Sdim    Inst.addOperand(MCOperand::CreateImm(TransferBytes));
1498263508Sdim  else // Decode Rm
1499263508Sdim    DecodeGPR64noxzrRegisterClass(Inst, Rm, Address, Decoder);
1500263508Sdim
1501263508Sdim  // Decode the source vector list.
1502263508Sdim  switch (NumVecs) {
1503263508Sdim  case 1:
1504263508Sdim    DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder);
1505263508Sdim    break;
1506263508Sdim  case 2:
1507263508Sdim    DecodeQPairRegisterClass(Inst, Rt, Address, Decoder);
1508263508Sdim    break;
1509263508Sdim  case 3:
1510263508Sdim    DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder);
1511263508Sdim    break;
1512263508Sdim  case 4:
1513263508Sdim    DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder);
1514263508Sdim  }
1515263508Sdim
1516263508Sdim  // Decode lane
1517263508Sdim  unsigned Q = fieldFromInstruction(Insn, 30, 1);
1518263508Sdim  unsigned S = fieldFromInstruction(Insn, 10, 3);
1519263508Sdim  unsigned lane = 0;
1520263508Sdim  // Calculate the number of lanes by number of vectors and transfered bytes.
1521263508Sdim  // NumLanes = 16 bytes / bytes of each lane
1522263508Sdim  unsigned NumLanes = 16 / (TransferBytes / NumVecs);
1523263508Sdim  switch (NumLanes) {
1524263508Sdim  case 16: // A vector has 16 lanes, each lane is 1 bytes.
1525263508Sdim    lane = (Q << 3) | S;
1526263508Sdim    break;
1527263508Sdim  case 8:
1528263508Sdim    lane = (Q << 2) | (S >> 1);
1529263508Sdim    break;
1530263508Sdim  case 4:
1531263508Sdim    lane = (Q << 1) | (S >> 2);
1532263508Sdim    break;
1533263508Sdim  case 2:
1534263508Sdim    lane = Q;
1535263508Sdim    break;
1536263508Sdim  }
1537263508Sdim  Inst.addOperand(MCOperand::CreateImm(lane));
1538263508Sdim
1539263508Sdim  return MCDisassembler::Success;
1540263508Sdim}
1541263508Sdim
1542263508Sdimstatic DecodeStatus DecodeSHLLInstruction(MCInst &Inst, unsigned Insn,
1543263508Sdim                                          uint64_t Address,
1544263508Sdim                                          const void *Decoder) {
1545263508Sdim  unsigned Rd = fieldFromInstruction(Insn, 0, 5);
1546263508Sdim  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
1547263508Sdim  unsigned size = fieldFromInstruction(Insn, 22, 2);
1548263508Sdim  unsigned Q = fieldFromInstruction(Insn, 30, 1);
1549263508Sdim
1550263508Sdim  DecodeFPR128RegisterClass(Inst, Rd, Address, Decoder);
1551263508Sdim
1552263508Sdim  if(Q)
1553263508Sdim    DecodeFPR128RegisterClass(Inst, Rn, Address, Decoder);
1554263508Sdim  else
1555263508Sdim    DecodeFPR64RegisterClass(Inst, Rn, Address, Decoder);
1556263508Sdim
1557263508Sdim  switch (size) {
1558263508Sdim  case 0:
1559263508Sdim    Inst.addOperand(MCOperand::CreateImm(8));
1560263508Sdim    break;
1561263508Sdim  case 1:
1562263508Sdim    Inst.addOperand(MCOperand::CreateImm(16));
1563263508Sdim    break;
1564263508Sdim  case 2:
1565263508Sdim    Inst.addOperand(MCOperand::CreateImm(32));
1566263508Sdim    break;
1567263508Sdim  default :
1568263508Sdim    return MCDisassembler::Fail;
1569263508Sdim  }
1570263508Sdim  return MCDisassembler::Success;
1571263508Sdim}
1572263508Sdim
1573