xref: /aosp_15_r20/external/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- ARMDisassembler.cpp - Disassembler for ARM/Thumb ISA --------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCDisassembler/MCDisassembler.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMAddressingModes.h"
12*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMBaseInfo.h"
13*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMMCExpr.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCFixedLenDisassembler.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrDesc.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LEB128.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
25*9880d681SAndroid Build Coastguard Worker #include <vector>
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "arm-disassembler"
30*9880d681SAndroid Build Coastguard Worker 
31*9880d681SAndroid Build Coastguard Worker typedef MCDisassembler::DecodeStatus DecodeStatus;
32*9880d681SAndroid Build Coastguard Worker 
33*9880d681SAndroid Build Coastguard Worker namespace {
34*9880d681SAndroid Build Coastguard Worker   // Handles the condition code status of instructions in IT blocks
35*9880d681SAndroid Build Coastguard Worker   class ITStatus
36*9880d681SAndroid Build Coastguard Worker   {
37*9880d681SAndroid Build Coastguard Worker     public:
38*9880d681SAndroid Build Coastguard Worker       // Returns the condition code for instruction in IT block
getITCC()39*9880d681SAndroid Build Coastguard Worker       unsigned getITCC() {
40*9880d681SAndroid Build Coastguard Worker         unsigned CC = ARMCC::AL;
41*9880d681SAndroid Build Coastguard Worker         if (instrInITBlock())
42*9880d681SAndroid Build Coastguard Worker           CC = ITStates.back();
43*9880d681SAndroid Build Coastguard Worker         return CC;
44*9880d681SAndroid Build Coastguard Worker       }
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker       // Advances the IT block state to the next T or E
advanceITState()47*9880d681SAndroid Build Coastguard Worker       void advanceITState() {
48*9880d681SAndroid Build Coastguard Worker         ITStates.pop_back();
49*9880d681SAndroid Build Coastguard Worker       }
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker       // Returns true if the current instruction is in an IT block
instrInITBlock()52*9880d681SAndroid Build Coastguard Worker       bool instrInITBlock() {
53*9880d681SAndroid Build Coastguard Worker         return !ITStates.empty();
54*9880d681SAndroid Build Coastguard Worker       }
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker       // Returns true if current instruction is the last instruction in an IT block
instrLastInITBlock()57*9880d681SAndroid Build Coastguard Worker       bool instrLastInITBlock() {
58*9880d681SAndroid Build Coastguard Worker         return ITStates.size() == 1;
59*9880d681SAndroid Build Coastguard Worker       }
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker       // Called when decoding an IT instruction. Sets the IT state for the following
62*9880d681SAndroid Build Coastguard Worker       // instructions that for the IT block. Firstcond and Mask correspond to the
63*9880d681SAndroid Build Coastguard Worker       // fields in the IT instruction encoding.
setITState(char Firstcond,char Mask)64*9880d681SAndroid Build Coastguard Worker       void setITState(char Firstcond, char Mask) {
65*9880d681SAndroid Build Coastguard Worker         // (3 - the number of trailing zeros) is the number of then / else.
66*9880d681SAndroid Build Coastguard Worker         unsigned CondBit0 = Firstcond & 1;
67*9880d681SAndroid Build Coastguard Worker         unsigned NumTZ = countTrailingZeros<uint8_t>(Mask);
68*9880d681SAndroid Build Coastguard Worker         unsigned char CCBits = static_cast<unsigned char>(Firstcond & 0xf);
69*9880d681SAndroid Build Coastguard Worker         assert(NumTZ <= 3 && "Invalid IT mask!");
70*9880d681SAndroid Build Coastguard Worker         // push condition codes onto the stack the correct order for the pops
71*9880d681SAndroid Build Coastguard Worker         for (unsigned Pos = NumTZ+1; Pos <= 3; ++Pos) {
72*9880d681SAndroid Build Coastguard Worker           bool T = ((Mask >> Pos) & 1) == CondBit0;
73*9880d681SAndroid Build Coastguard Worker           if (T)
74*9880d681SAndroid Build Coastguard Worker             ITStates.push_back(CCBits);
75*9880d681SAndroid Build Coastguard Worker           else
76*9880d681SAndroid Build Coastguard Worker             ITStates.push_back(CCBits ^ 1);
77*9880d681SAndroid Build Coastguard Worker         }
78*9880d681SAndroid Build Coastguard Worker         ITStates.push_back(CCBits);
79*9880d681SAndroid Build Coastguard Worker       }
80*9880d681SAndroid Build Coastguard Worker 
81*9880d681SAndroid Build Coastguard Worker     private:
82*9880d681SAndroid Build Coastguard Worker       std::vector<unsigned char> ITStates;
83*9880d681SAndroid Build Coastguard Worker   };
84*9880d681SAndroid Build Coastguard Worker }
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker namespace {
87*9880d681SAndroid Build Coastguard Worker /// ARM disassembler for all ARM platforms.
88*9880d681SAndroid Build Coastguard Worker class ARMDisassembler : public MCDisassembler {
89*9880d681SAndroid Build Coastguard Worker public:
ARMDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)90*9880d681SAndroid Build Coastguard Worker   ARMDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) :
91*9880d681SAndroid Build Coastguard Worker     MCDisassembler(STI, Ctx) {
92*9880d681SAndroid Build Coastguard Worker   }
93*9880d681SAndroid Build Coastguard Worker 
~ARMDisassembler()94*9880d681SAndroid Build Coastguard Worker   ~ARMDisassembler() override {}
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
97*9880d681SAndroid Build Coastguard Worker                               ArrayRef<uint8_t> Bytes, uint64_t Address,
98*9880d681SAndroid Build Coastguard Worker                               raw_ostream &VStream,
99*9880d681SAndroid Build Coastguard Worker                               raw_ostream &CStream) const override;
100*9880d681SAndroid Build Coastguard Worker };
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker /// Thumb disassembler for all Thumb platforms.
103*9880d681SAndroid Build Coastguard Worker class ThumbDisassembler : public MCDisassembler {
104*9880d681SAndroid Build Coastguard Worker public:
ThumbDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)105*9880d681SAndroid Build Coastguard Worker   ThumbDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) :
106*9880d681SAndroid Build Coastguard Worker     MCDisassembler(STI, Ctx) {
107*9880d681SAndroid Build Coastguard Worker   }
108*9880d681SAndroid Build Coastguard Worker 
~ThumbDisassembler()109*9880d681SAndroid Build Coastguard Worker   ~ThumbDisassembler() override {}
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
112*9880d681SAndroid Build Coastguard Worker                               ArrayRef<uint8_t> Bytes, uint64_t Address,
113*9880d681SAndroid Build Coastguard Worker                               raw_ostream &VStream,
114*9880d681SAndroid Build Coastguard Worker                               raw_ostream &CStream) const override;
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker private:
117*9880d681SAndroid Build Coastguard Worker   mutable ITStatus ITBlock;
118*9880d681SAndroid Build Coastguard Worker   DecodeStatus AddThumbPredicate(MCInst&) const;
119*9880d681SAndroid Build Coastguard Worker   void UpdateThumbVFPPredicate(MCInst&) const;
120*9880d681SAndroid Build Coastguard Worker };
121*9880d681SAndroid Build Coastguard Worker }
122*9880d681SAndroid Build Coastguard Worker 
Check(DecodeStatus & Out,DecodeStatus In)123*9880d681SAndroid Build Coastguard Worker static bool Check(DecodeStatus &Out, DecodeStatus In) {
124*9880d681SAndroid Build Coastguard Worker   switch (In) {
125*9880d681SAndroid Build Coastguard Worker     case MCDisassembler::Success:
126*9880d681SAndroid Build Coastguard Worker       // Out stays the same.
127*9880d681SAndroid Build Coastguard Worker       return true;
128*9880d681SAndroid Build Coastguard Worker     case MCDisassembler::SoftFail:
129*9880d681SAndroid Build Coastguard Worker       Out = In;
130*9880d681SAndroid Build Coastguard Worker       return true;
131*9880d681SAndroid Build Coastguard Worker     case MCDisassembler::Fail:
132*9880d681SAndroid Build Coastguard Worker       Out = In;
133*9880d681SAndroid Build Coastguard Worker       return false;
134*9880d681SAndroid Build Coastguard Worker   }
135*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Invalid DecodeStatus!");
136*9880d681SAndroid Build Coastguard Worker }
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker 
139*9880d681SAndroid Build Coastguard Worker // Forward declare these because the autogenerated code will reference them.
140*9880d681SAndroid Build Coastguard Worker // Definitions are further down.
141*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
142*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
143*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGPRnopcRegisterClass(MCInst &Inst,
144*9880d681SAndroid Build Coastguard Worker                                                unsigned RegNo, uint64_t Address,
145*9880d681SAndroid Build Coastguard Worker                                                const void *Decoder);
146*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGPRwithAPSRRegisterClass(MCInst &Inst,
147*9880d681SAndroid Build Coastguard Worker                                                unsigned RegNo, uint64_t Address,
148*9880d681SAndroid Build Coastguard Worker                                                const void *Decoder);
149*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodetGPRRegisterClass(MCInst &Inst, unsigned RegNo,
150*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
151*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo,
152*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
153*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecoderGPRRegisterClass(MCInst &Inst, unsigned RegNo,
154*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
155*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo,
156*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
157*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSPRRegisterClass(MCInst &Inst, unsigned RegNo,
158*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
159*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPRRegisterClass(MCInst &Inst, unsigned RegNo,
160*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
161*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPR_8RegisterClass(MCInst &Inst, unsigned RegNo,
162*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
163*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPR_VFP2RegisterClass(MCInst &Inst,
164*9880d681SAndroid Build Coastguard Worker                                                 unsigned RegNo,
165*9880d681SAndroid Build Coastguard Worker                                                 uint64_t Address,
166*9880d681SAndroid Build Coastguard Worker                                                 const void *Decoder);
167*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeQPRRegisterClass(MCInst &Inst, unsigned RegNo,
168*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
169*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPairRegisterClass(MCInst &Inst, unsigned RegNo,
170*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder);
171*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPairSpacedRegisterClass(MCInst &Inst,
172*9880d681SAndroid Build Coastguard Worker                                unsigned RegNo, uint64_t Address,
173*9880d681SAndroid Build Coastguard Worker                                const void *Decoder);
174*9880d681SAndroid Build Coastguard Worker 
175*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val,
176*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
177*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val,
178*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
179*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Val,
180*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
181*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSPRRegListOperand(MCInst &Inst, unsigned Val,
182*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
183*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPRRegListOperand(MCInst &Inst, unsigned Val,
184*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeBitfieldMaskOperand(MCInst &Inst, unsigned Insn,
187*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
188*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn,
189*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
190*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode2IdxInstruction(MCInst &Inst,
191*9880d681SAndroid Build Coastguard Worker                                                   unsigned Insn,
192*9880d681SAndroid Build Coastguard Worker                                                   uint64_t Address,
193*9880d681SAndroid Build Coastguard Worker                                                   const void *Decoder);
194*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSORegMemOperand(MCInst &Inst, unsigned Insn,
195*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
196*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode3Instruction(MCInst &Inst,unsigned Insn,
197*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
198*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Insn,
199*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
200*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSORegRegOperand(MCInst &Inst, unsigned Insn,
201*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
202*9880d681SAndroid Build Coastguard Worker 
203*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeMemMultipleWritebackInstruction(MCInst & Inst,
204*9880d681SAndroid Build Coastguard Worker                                                   unsigned Insn,
205*9880d681SAndroid Build Coastguard Worker                                                   uint64_t Adddress,
206*9880d681SAndroid Build Coastguard Worker                                                   const void *Decoder);
207*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2MOVTWInstruction(MCInst &Inst, unsigned Insn,
208*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
209*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeArmMOVTWInstruction(MCInst &Inst, unsigned Insn,
210*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
211*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSMLAInstruction(MCInst &Inst, unsigned Insn,
212*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
213*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeHINTInstruction(MCInst &Inst, unsigned Insn,
214*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
215*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeCPSInstruction(MCInst &Inst, unsigned Insn,
216*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
217*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeTSTInstruction(MCInst &Inst, unsigned Insn,
218*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
219*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSETPANInstruction(MCInst &Inst, unsigned Insn,
220*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
221*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2CPSInstruction(MCInst &Inst, unsigned Insn,
222*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
223*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrModeImm12Operand(MCInst &Inst, unsigned Val,
224*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
225*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode5Operand(MCInst &Inst, unsigned Val,
226*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
227*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode5FP16Operand(MCInst &Inst, unsigned Val,
228*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
229*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode7Operand(MCInst &Inst, unsigned Val,
230*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
231*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2BInstruction(MCInst &Inst, unsigned Insn,
232*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
233*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeBranchImmInstruction(MCInst &Inst,unsigned Insn,
234*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
235*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode6Operand(MCInst &Inst, unsigned Val,
236*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
237*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDST1Instruction(MCInst &Inst, unsigned Val,
238*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
239*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDST2Instruction(MCInst &Inst, unsigned Val,
240*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
241*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDST3Instruction(MCInst &Inst, unsigned Val,
242*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
243*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDST4Instruction(MCInst &Inst, unsigned Val,
244*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
245*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDInstruction(MCInst &Inst, unsigned Val,
246*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
247*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVSTInstruction(MCInst &Inst, unsigned Val,
248*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
249*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD1DupInstruction(MCInst &Inst, unsigned Val,
250*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
251*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Val,
252*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
253*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD3DupInstruction(MCInst &Inst, unsigned Val,
254*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
255*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD4DupInstruction(MCInst &Inst, unsigned Val,
256*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
257*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeNEONModImmInstruction(MCInst &Inst,unsigned Val,
258*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
259*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVSHLMaxInstruction(MCInst &Inst, unsigned Val,
260*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
261*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeShiftRight8Imm(MCInst &Inst, unsigned Val,
262*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
263*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeShiftRight16Imm(MCInst &Inst, unsigned Val,
264*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
265*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeShiftRight32Imm(MCInst &Inst, unsigned Val,
266*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
267*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeShiftRight64Imm(MCInst &Inst, unsigned Val,
268*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
269*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeTBLInstruction(MCInst &Inst, unsigned Insn,
270*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
271*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodePostIdxReg(MCInst &Inst, unsigned Insn,
272*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
273*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeCoprocessor(MCInst &Inst, unsigned Insn,
274*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
275*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeMemBarrierOption(MCInst &Inst, unsigned Insn,
276*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
277*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeInstSyncBarrierOption(MCInst &Inst, unsigned Insn,
278*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
279*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Insn,
280*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
281*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeBankedReg(MCInst &Inst, unsigned Insn,
282*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
283*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDoubleRegLoad(MCInst &Inst, unsigned Insn,
284*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
285*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDoubleRegStore(MCInst &Inst, unsigned Insn,
286*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
287*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeLDRPreImm(MCInst &Inst, unsigned Insn,
288*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
289*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeLDRPreReg(MCInst &Inst, unsigned Insn,
290*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
291*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSTRPreImm(MCInst &Inst, unsigned Insn,
292*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
293*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSTRPreReg(MCInst &Inst, unsigned Insn,
294*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
295*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD1LN(MCInst &Inst, unsigned Insn,
296*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
297*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD2LN(MCInst &Inst, unsigned Insn,
298*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
299*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD3LN(MCInst &Inst, unsigned Insn,
300*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
301*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD4LN(MCInst &Inst, unsigned Insn,
302*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
303*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVST1LN(MCInst &Inst, unsigned Insn,
304*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
305*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVST2LN(MCInst &Inst, unsigned Insn,
306*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
307*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVST3LN(MCInst &Inst, unsigned Insn,
308*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
309*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVST4LN(MCInst &Inst, unsigned Insn,
310*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
311*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVMOVSRR(MCInst &Inst, unsigned Insn,
312*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
313*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVMOVRRS(MCInst &Inst, unsigned Insn,
314*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
315*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSwap(MCInst &Inst, unsigned Insn,
316*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
317*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVCVTD(MCInst &Inst, unsigned Insn,
318*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
319*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVCVTQ(MCInst &Inst, unsigned Insn,
320*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
321*9880d681SAndroid Build Coastguard Worker 
322*9880d681SAndroid Build Coastguard Worker 
323*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddSpecialReg(MCInst &Inst, uint16_t Insn,
324*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
325*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbBROperand(MCInst &Inst, unsigned Val,
326*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
327*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2BROperand(MCInst &Inst, unsigned Val,
328*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
329*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbCmpBROperand(MCInst &Inst, unsigned Val,
330*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
331*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddrModeRR(MCInst &Inst, unsigned Val,
332*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
333*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddrModeIS(MCInst &Inst, unsigned Val,
334*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
335*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddrModePC(MCInst &Inst, unsigned Val,
336*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
337*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddrModeSP(MCInst &Inst, unsigned Val,
338*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
339*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeSOReg(MCInst &Inst, unsigned Val,
340*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
341*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Val,
342*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
343*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
344*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void* Decoder);
345*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
346*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void* Decoder);
347*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadT(MCInst &Inst, unsigned Insn,
348*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void* Decoder);
349*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
350*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void* Decoder);
351*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2Imm8S4(MCInst &Inst, unsigned Val,
352*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
353*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeImm8s4(MCInst &Inst, unsigned Val,
354*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
355*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeImm0_1020s4(MCInst &Inst,unsigned Val,
356*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
357*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2Imm8(MCInst &Inst, unsigned Val,
358*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
359*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeImm8(MCInst &Inst, unsigned Val,
360*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
361*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddSPImm(MCInst &Inst, uint16_t Val,
362*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
363*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddSPReg(MCInst &Inst, uint16_t Insn,
364*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
365*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbCPS(MCInst &Inst, uint16_t Insn,
366*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
367*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeQADDInstruction(MCInst &Inst, unsigned Insn,
368*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
369*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbBLXOffset(MCInst &Inst, unsigned Insn,
370*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
371*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeImm12(MCInst &Inst, unsigned Val,
372*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
373*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbTableBranch(MCInst &Inst, unsigned Val,
374*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
375*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumb2BCCInstruction(MCInst &Inst, unsigned Val,
376*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
377*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2SOImm(MCInst &Inst, unsigned Val,
378*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
379*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbBCCTargetOperand(MCInst &Inst,unsigned Val,
380*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
381*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbBLTargetOperand(MCInst &Inst, unsigned Val,
382*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
383*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeIT(MCInst &Inst, unsigned Val,
384*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
385*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LDRDPreInstruction(MCInst &Inst,unsigned Insn,
386*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
387*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2STRDPreInstruction(MCInst &Inst,unsigned Insn,
388*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder);
389*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2Adr(MCInst &Inst, unsigned Val,
390*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
391*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LdStPre(MCInst &Inst, unsigned Val,
392*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
393*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2ShifterImmOperand(MCInst &Inst, unsigned Val,
394*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
395*9880d681SAndroid Build Coastguard Worker 
396*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val,
397*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder);
398*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecoderForMRRC2AndMCRR2(llvm::MCInst &Inst, unsigned Val,
399*9880d681SAndroid Build Coastguard Worker                                             uint64_t Address, const void *Decoder);
400*9880d681SAndroid Build Coastguard Worker #include "ARMGenDisassemblerTables.inc"
401*9880d681SAndroid Build Coastguard Worker 
createARMDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)402*9880d681SAndroid Build Coastguard Worker static MCDisassembler *createARMDisassembler(const Target &T,
403*9880d681SAndroid Build Coastguard Worker                                              const MCSubtargetInfo &STI,
404*9880d681SAndroid Build Coastguard Worker                                              MCContext &Ctx) {
405*9880d681SAndroid Build Coastguard Worker   return new ARMDisassembler(STI, Ctx);
406*9880d681SAndroid Build Coastguard Worker }
407*9880d681SAndroid Build Coastguard Worker 
createThumbDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)408*9880d681SAndroid Build Coastguard Worker static MCDisassembler *createThumbDisassembler(const Target &T,
409*9880d681SAndroid Build Coastguard Worker                                                const MCSubtargetInfo &STI,
410*9880d681SAndroid Build Coastguard Worker                                                MCContext &Ctx) {
411*9880d681SAndroid Build Coastguard Worker   return new ThumbDisassembler(STI, Ctx);
412*9880d681SAndroid Build Coastguard Worker }
413*9880d681SAndroid Build Coastguard Worker 
414*9880d681SAndroid Build Coastguard Worker // Post-decoding checks
checkDecodedInstruction(MCInst & MI,uint64_t & Size,uint64_t Address,raw_ostream & OS,raw_ostream & CS,uint32_t Insn,DecodeStatus Result)415*9880d681SAndroid Build Coastguard Worker static DecodeStatus checkDecodedInstruction(MCInst &MI, uint64_t &Size,
416*9880d681SAndroid Build Coastguard Worker                                             uint64_t Address, raw_ostream &OS,
417*9880d681SAndroid Build Coastguard Worker                                             raw_ostream &CS,
418*9880d681SAndroid Build Coastguard Worker                                             uint32_t Insn,
419*9880d681SAndroid Build Coastguard Worker                                             DecodeStatus Result)
420*9880d681SAndroid Build Coastguard Worker {
421*9880d681SAndroid Build Coastguard Worker   switch (MI.getOpcode()) {
422*9880d681SAndroid Build Coastguard Worker     case ARM::HVC: {
423*9880d681SAndroid Build Coastguard Worker       // HVC is undefined if condition = 0xf otherwise upredictable
424*9880d681SAndroid Build Coastguard Worker       // if condition != 0xe
425*9880d681SAndroid Build Coastguard Worker       uint32_t Cond = (Insn >> 28) & 0xF;
426*9880d681SAndroid Build Coastguard Worker       if (Cond == 0xF)
427*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
428*9880d681SAndroid Build Coastguard Worker       if (Cond != 0xE)
429*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::SoftFail;
430*9880d681SAndroid Build Coastguard Worker       return Result;
431*9880d681SAndroid Build Coastguard Worker     }
432*9880d681SAndroid Build Coastguard Worker     default: return Result;
433*9880d681SAndroid Build Coastguard Worker   }
434*9880d681SAndroid Build Coastguard Worker }
435*9880d681SAndroid Build Coastguard Worker 
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & OS,raw_ostream & CS) const436*9880d681SAndroid Build Coastguard Worker DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
437*9880d681SAndroid Build Coastguard Worker                                              ArrayRef<uint8_t> Bytes,
438*9880d681SAndroid Build Coastguard Worker                                              uint64_t Address, raw_ostream &OS,
439*9880d681SAndroid Build Coastguard Worker                                              raw_ostream &CS) const {
440*9880d681SAndroid Build Coastguard Worker   CommentStream = &CS;
441*9880d681SAndroid Build Coastguard Worker 
442*9880d681SAndroid Build Coastguard Worker   assert(!STI.getFeatureBits()[ARM::ModeThumb] &&
443*9880d681SAndroid Build Coastguard Worker          "Asked to disassemble an ARM instruction but Subtarget is in Thumb "
444*9880d681SAndroid Build Coastguard Worker          "mode!");
445*9880d681SAndroid Build Coastguard Worker 
446*9880d681SAndroid Build Coastguard Worker   // We want to read exactly 4 bytes of data.
447*9880d681SAndroid Build Coastguard Worker   if (Bytes.size() < 4) {
448*9880d681SAndroid Build Coastguard Worker     Size = 0;
449*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
450*9880d681SAndroid Build Coastguard Worker   }
451*9880d681SAndroid Build Coastguard Worker 
452*9880d681SAndroid Build Coastguard Worker   // Encoded as a small-endian 32-bit word in the stream.
453*9880d681SAndroid Build Coastguard Worker   uint32_t Insn =
454*9880d681SAndroid Build Coastguard Worker       (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
455*9880d681SAndroid Build Coastguard Worker 
456*9880d681SAndroid Build Coastguard Worker   // Calling the auto-generated decoder function.
457*9880d681SAndroid Build Coastguard Worker   DecodeStatus Result =
458*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTableARM32, MI, Insn, Address, this, STI);
459*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
460*9880d681SAndroid Build Coastguard Worker     Size = 4;
461*9880d681SAndroid Build Coastguard Worker     return checkDecodedInstruction(MI, Size, Address, OS, CS, Insn, Result);
462*9880d681SAndroid Build Coastguard Worker   }
463*9880d681SAndroid Build Coastguard Worker 
464*9880d681SAndroid Build Coastguard Worker   // VFP and NEON instructions, similarly, are shared between ARM
465*9880d681SAndroid Build Coastguard Worker   // and Thumb modes.
466*9880d681SAndroid Build Coastguard Worker   Result = decodeInstruction(DecoderTableVFP32, MI, Insn, Address, this, STI);
467*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
468*9880d681SAndroid Build Coastguard Worker     Size = 4;
469*9880d681SAndroid Build Coastguard Worker     return Result;
470*9880d681SAndroid Build Coastguard Worker   }
471*9880d681SAndroid Build Coastguard Worker 
472*9880d681SAndroid Build Coastguard Worker   Result = decodeInstruction(DecoderTableVFPV832, MI, Insn, Address, this, STI);
473*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
474*9880d681SAndroid Build Coastguard Worker     Size = 4;
475*9880d681SAndroid Build Coastguard Worker     return Result;
476*9880d681SAndroid Build Coastguard Worker   }
477*9880d681SAndroid Build Coastguard Worker 
478*9880d681SAndroid Build Coastguard Worker   Result =
479*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTableNEONData32, MI, Insn, Address, this, STI);
480*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
481*9880d681SAndroid Build Coastguard Worker     Size = 4;
482*9880d681SAndroid Build Coastguard Worker     // Add a fake predicate operand, because we share these instruction
483*9880d681SAndroid Build Coastguard Worker     // definitions with Thumb2 where these instructions are predicable.
484*9880d681SAndroid Build Coastguard Worker     if (!DecodePredicateOperand(MI, 0xE, Address, this))
485*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
486*9880d681SAndroid Build Coastguard Worker     return Result;
487*9880d681SAndroid Build Coastguard Worker   }
488*9880d681SAndroid Build Coastguard Worker 
489*9880d681SAndroid Build Coastguard Worker   Result = decodeInstruction(DecoderTableNEONLoadStore32, MI, Insn, Address,
490*9880d681SAndroid Build Coastguard Worker                              this, STI);
491*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
492*9880d681SAndroid Build Coastguard Worker     Size = 4;
493*9880d681SAndroid Build Coastguard Worker     // Add a fake predicate operand, because we share these instruction
494*9880d681SAndroid Build Coastguard Worker     // definitions with Thumb2 where these instructions are predicable.
495*9880d681SAndroid Build Coastguard Worker     if (!DecodePredicateOperand(MI, 0xE, Address, this))
496*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
497*9880d681SAndroid Build Coastguard Worker     return Result;
498*9880d681SAndroid Build Coastguard Worker   }
499*9880d681SAndroid Build Coastguard Worker 
500*9880d681SAndroid Build Coastguard Worker   Result =
501*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTableNEONDup32, MI, Insn, Address, this, STI);
502*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
503*9880d681SAndroid Build Coastguard Worker     Size = 4;
504*9880d681SAndroid Build Coastguard Worker     // Add a fake predicate operand, because we share these instruction
505*9880d681SAndroid Build Coastguard Worker     // definitions with Thumb2 where these instructions are predicable.
506*9880d681SAndroid Build Coastguard Worker     if (!DecodePredicateOperand(MI, 0xE, Address, this))
507*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
508*9880d681SAndroid Build Coastguard Worker     return Result;
509*9880d681SAndroid Build Coastguard Worker   }
510*9880d681SAndroid Build Coastguard Worker 
511*9880d681SAndroid Build Coastguard Worker   Result =
512*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTablev8NEON32, MI, Insn, Address, this, STI);
513*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
514*9880d681SAndroid Build Coastguard Worker     Size = 4;
515*9880d681SAndroid Build Coastguard Worker     return Result;
516*9880d681SAndroid Build Coastguard Worker   }
517*9880d681SAndroid Build Coastguard Worker 
518*9880d681SAndroid Build Coastguard Worker   Result =
519*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTablev8Crypto32, MI, Insn, Address, this, STI);
520*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
521*9880d681SAndroid Build Coastguard Worker     Size = 4;
522*9880d681SAndroid Build Coastguard Worker     return Result;
523*9880d681SAndroid Build Coastguard Worker   }
524*9880d681SAndroid Build Coastguard Worker 
525*9880d681SAndroid Build Coastguard Worker   Size = 0;
526*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Fail;
527*9880d681SAndroid Build Coastguard Worker }
528*9880d681SAndroid Build Coastguard Worker 
529*9880d681SAndroid Build Coastguard Worker namespace llvm {
530*9880d681SAndroid Build Coastguard Worker extern const MCInstrDesc ARMInsts[];
531*9880d681SAndroid Build Coastguard Worker }
532*9880d681SAndroid Build Coastguard Worker 
533*9880d681SAndroid Build Coastguard Worker /// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
534*9880d681SAndroid Build Coastguard Worker /// immediate Value in the MCInst.  The immediate Value has had any PC
535*9880d681SAndroid Build Coastguard Worker /// adjustment made by the caller.  If the instruction is a branch instruction
536*9880d681SAndroid Build Coastguard Worker /// then isBranch is true, else false.  If the getOpInfo() function was set as
537*9880d681SAndroid Build Coastguard Worker /// part of the setupForSymbolicDisassembly() call then that function is called
538*9880d681SAndroid Build Coastguard Worker /// to get any symbolic information at the Address for this instruction.  If
539*9880d681SAndroid Build Coastguard Worker /// that returns non-zero then the symbolic information it returns is used to
540*9880d681SAndroid Build Coastguard Worker /// create an MCExpr and that is added as an operand to the MCInst.  If
541*9880d681SAndroid Build Coastguard Worker /// getOpInfo() returns zero and isBranch is true then a symbol look up for
542*9880d681SAndroid Build Coastguard Worker /// Value is done and if a symbol is found an MCExpr is created with that, else
543*9880d681SAndroid Build Coastguard Worker /// an MCExpr with Value is created.  This function returns true if it adds an
544*9880d681SAndroid Build Coastguard Worker /// operand to the MCInst and false otherwise.
tryAddingSymbolicOperand(uint64_t Address,int32_t Value,bool isBranch,uint64_t InstSize,MCInst & MI,const void * Decoder)545*9880d681SAndroid Build Coastguard Worker static bool tryAddingSymbolicOperand(uint64_t Address, int32_t Value,
546*9880d681SAndroid Build Coastguard Worker                                      bool isBranch, uint64_t InstSize,
547*9880d681SAndroid Build Coastguard Worker                                      MCInst &MI, const void *Decoder) {
548*9880d681SAndroid Build Coastguard Worker   const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
549*9880d681SAndroid Build Coastguard Worker   // FIXME: Does it make sense for value to be negative?
550*9880d681SAndroid Build Coastguard Worker   return Dis->tryAddingSymbolicOperand(MI, (uint32_t)Value, Address, isBranch,
551*9880d681SAndroid Build Coastguard Worker                                        /* Offset */ 0, InstSize);
552*9880d681SAndroid Build Coastguard Worker }
553*9880d681SAndroid Build Coastguard Worker 
554*9880d681SAndroid Build Coastguard Worker /// tryAddingPcLoadReferenceComment - trys to add a comment as to what is being
555*9880d681SAndroid Build Coastguard Worker /// referenced by a load instruction with the base register that is the Pc.
556*9880d681SAndroid Build Coastguard Worker /// These can often be values in a literal pool near the Address of the
557*9880d681SAndroid Build Coastguard Worker /// instruction.  The Address of the instruction and its immediate Value are
558*9880d681SAndroid Build Coastguard Worker /// used as a possible literal pool entry.  The SymbolLookUp call back will
559*9880d681SAndroid Build Coastguard Worker /// return the name of a symbol referenced by the literal pool's entry if
560*9880d681SAndroid Build Coastguard Worker /// the referenced address is that of a symbol.  Or it will return a pointer to
561*9880d681SAndroid Build Coastguard Worker /// a literal 'C' string if the referenced address of the literal pool's entry
562*9880d681SAndroid Build Coastguard Worker /// is an address into a section with 'C' string literals.
tryAddingPcLoadReferenceComment(uint64_t Address,int Value,const void * Decoder)563*9880d681SAndroid Build Coastguard Worker static void tryAddingPcLoadReferenceComment(uint64_t Address, int Value,
564*9880d681SAndroid Build Coastguard Worker                                             const void *Decoder) {
565*9880d681SAndroid Build Coastguard Worker   const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
566*9880d681SAndroid Build Coastguard Worker   Dis->tryAddingPcLoadReferenceComment(Value, Address);
567*9880d681SAndroid Build Coastguard Worker }
568*9880d681SAndroid Build Coastguard Worker 
569*9880d681SAndroid Build Coastguard Worker // Thumb1 instructions don't have explicit S bits.  Rather, they
570*9880d681SAndroid Build Coastguard Worker // implicitly set CPSR.  Since it's not represented in the encoding, the
571*9880d681SAndroid Build Coastguard Worker // auto-generated decoder won't inject the CPSR operand.  We need to fix
572*9880d681SAndroid Build Coastguard Worker // that as a post-pass.
AddThumb1SBit(MCInst & MI,bool InITBlock)573*9880d681SAndroid Build Coastguard Worker static void AddThumb1SBit(MCInst &MI, bool InITBlock) {
574*9880d681SAndroid Build Coastguard Worker   const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
575*9880d681SAndroid Build Coastguard Worker   unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
576*9880d681SAndroid Build Coastguard Worker   MCInst::iterator I = MI.begin();
577*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumOps; ++i, ++I) {
578*9880d681SAndroid Build Coastguard Worker     if (I == MI.end()) break;
579*9880d681SAndroid Build Coastguard Worker     if (OpInfo[i].isOptionalDef() && OpInfo[i].RegClass == ARM::CCRRegClassID) {
580*9880d681SAndroid Build Coastguard Worker       if (i > 0 && OpInfo[i-1].isPredicate()) continue;
581*9880d681SAndroid Build Coastguard Worker       MI.insert(I, MCOperand::createReg(InITBlock ? 0 : ARM::CPSR));
582*9880d681SAndroid Build Coastguard Worker       return;
583*9880d681SAndroid Build Coastguard Worker     }
584*9880d681SAndroid Build Coastguard Worker   }
585*9880d681SAndroid Build Coastguard Worker 
586*9880d681SAndroid Build Coastguard Worker   MI.insert(I, MCOperand::createReg(InITBlock ? 0 : ARM::CPSR));
587*9880d681SAndroid Build Coastguard Worker }
588*9880d681SAndroid Build Coastguard Worker 
589*9880d681SAndroid Build Coastguard Worker // Most Thumb instructions don't have explicit predicates in the
590*9880d681SAndroid Build Coastguard Worker // encoding, but rather get their predicates from IT context.  We need
591*9880d681SAndroid Build Coastguard Worker // to fix up the predicate operands using this context information as a
592*9880d681SAndroid Build Coastguard Worker // post-pass.
593*9880d681SAndroid Build Coastguard Worker MCDisassembler::DecodeStatus
AddThumbPredicate(MCInst & MI) const594*9880d681SAndroid Build Coastguard Worker ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
595*9880d681SAndroid Build Coastguard Worker   MCDisassembler::DecodeStatus S = Success;
596*9880d681SAndroid Build Coastguard Worker 
597*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &FeatureBits = getSubtargetInfo().getFeatureBits();
598*9880d681SAndroid Build Coastguard Worker 
599*9880d681SAndroid Build Coastguard Worker   // A few instructions actually have predicates encoded in them.  Don't
600*9880d681SAndroid Build Coastguard Worker   // try to overwrite it if we're seeing one of those.
601*9880d681SAndroid Build Coastguard Worker   switch (MI.getOpcode()) {
602*9880d681SAndroid Build Coastguard Worker     case ARM::tBcc:
603*9880d681SAndroid Build Coastguard Worker     case ARM::t2Bcc:
604*9880d681SAndroid Build Coastguard Worker     case ARM::tCBZ:
605*9880d681SAndroid Build Coastguard Worker     case ARM::tCBNZ:
606*9880d681SAndroid Build Coastguard Worker     case ARM::tCPS:
607*9880d681SAndroid Build Coastguard Worker     case ARM::t2CPS3p:
608*9880d681SAndroid Build Coastguard Worker     case ARM::t2CPS2p:
609*9880d681SAndroid Build Coastguard Worker     case ARM::t2CPS1p:
610*9880d681SAndroid Build Coastguard Worker     case ARM::tMOVSr:
611*9880d681SAndroid Build Coastguard Worker     case ARM::tSETEND:
612*9880d681SAndroid Build Coastguard Worker       // Some instructions (mostly conditional branches) are not
613*9880d681SAndroid Build Coastguard Worker       // allowed in IT blocks.
614*9880d681SAndroid Build Coastguard Worker       if (ITBlock.instrInITBlock())
615*9880d681SAndroid Build Coastguard Worker         S = SoftFail;
616*9880d681SAndroid Build Coastguard Worker       else
617*9880d681SAndroid Build Coastguard Worker         return Success;
618*9880d681SAndroid Build Coastguard Worker       break;
619*9880d681SAndroid Build Coastguard Worker     case ARM::t2HINT:
620*9880d681SAndroid Build Coastguard Worker       if (MI.getOperand(0).getImm() == 0x10 && (FeatureBits[ARM::FeatureRAS]) != 0)
621*9880d681SAndroid Build Coastguard Worker         S = SoftFail;
622*9880d681SAndroid Build Coastguard Worker       break;
623*9880d681SAndroid Build Coastguard Worker     case ARM::tB:
624*9880d681SAndroid Build Coastguard Worker     case ARM::t2B:
625*9880d681SAndroid Build Coastguard Worker     case ARM::t2TBB:
626*9880d681SAndroid Build Coastguard Worker     case ARM::t2TBH:
627*9880d681SAndroid Build Coastguard Worker       // Some instructions (mostly unconditional branches) can
628*9880d681SAndroid Build Coastguard Worker       // only appears at the end of, or outside of, an IT.
629*9880d681SAndroid Build Coastguard Worker       if (ITBlock.instrInITBlock() && !ITBlock.instrLastInITBlock())
630*9880d681SAndroid Build Coastguard Worker         S = SoftFail;
631*9880d681SAndroid Build Coastguard Worker       break;
632*9880d681SAndroid Build Coastguard Worker     default:
633*9880d681SAndroid Build Coastguard Worker       break;
634*9880d681SAndroid Build Coastguard Worker   }
635*9880d681SAndroid Build Coastguard Worker 
636*9880d681SAndroid Build Coastguard Worker   // If we're in an IT block, base the predicate on that.  Otherwise,
637*9880d681SAndroid Build Coastguard Worker   // assume a predicate of AL.
638*9880d681SAndroid Build Coastguard Worker   unsigned CC;
639*9880d681SAndroid Build Coastguard Worker   CC = ITBlock.getITCC();
640*9880d681SAndroid Build Coastguard Worker   if (CC == 0xF)
641*9880d681SAndroid Build Coastguard Worker     CC = ARMCC::AL;
642*9880d681SAndroid Build Coastguard Worker   if (ITBlock.instrInITBlock())
643*9880d681SAndroid Build Coastguard Worker     ITBlock.advanceITState();
644*9880d681SAndroid Build Coastguard Worker 
645*9880d681SAndroid Build Coastguard Worker   const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
646*9880d681SAndroid Build Coastguard Worker   unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
647*9880d681SAndroid Build Coastguard Worker   MCInst::iterator I = MI.begin();
648*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumOps; ++i, ++I) {
649*9880d681SAndroid Build Coastguard Worker     if (I == MI.end()) break;
650*9880d681SAndroid Build Coastguard Worker     if (OpInfo[i].isPredicate()) {
651*9880d681SAndroid Build Coastguard Worker       I = MI.insert(I, MCOperand::createImm(CC));
652*9880d681SAndroid Build Coastguard Worker       ++I;
653*9880d681SAndroid Build Coastguard Worker       if (CC == ARMCC::AL)
654*9880d681SAndroid Build Coastguard Worker         MI.insert(I, MCOperand::createReg(0));
655*9880d681SAndroid Build Coastguard Worker       else
656*9880d681SAndroid Build Coastguard Worker         MI.insert(I, MCOperand::createReg(ARM::CPSR));
657*9880d681SAndroid Build Coastguard Worker       return S;
658*9880d681SAndroid Build Coastguard Worker     }
659*9880d681SAndroid Build Coastguard Worker   }
660*9880d681SAndroid Build Coastguard Worker 
661*9880d681SAndroid Build Coastguard Worker   I = MI.insert(I, MCOperand::createImm(CC));
662*9880d681SAndroid Build Coastguard Worker   ++I;
663*9880d681SAndroid Build Coastguard Worker   if (CC == ARMCC::AL)
664*9880d681SAndroid Build Coastguard Worker     MI.insert(I, MCOperand::createReg(0));
665*9880d681SAndroid Build Coastguard Worker   else
666*9880d681SAndroid Build Coastguard Worker     MI.insert(I, MCOperand::createReg(ARM::CPSR));
667*9880d681SAndroid Build Coastguard Worker 
668*9880d681SAndroid Build Coastguard Worker   return S;
669*9880d681SAndroid Build Coastguard Worker }
670*9880d681SAndroid Build Coastguard Worker 
671*9880d681SAndroid Build Coastguard Worker // Thumb VFP instructions are a special case.  Because we share their
672*9880d681SAndroid Build Coastguard Worker // encodings between ARM and Thumb modes, and they are predicable in ARM
673*9880d681SAndroid Build Coastguard Worker // mode, the auto-generated decoder will give them an (incorrect)
674*9880d681SAndroid Build Coastguard Worker // predicate operand.  We need to rewrite these operands based on the IT
675*9880d681SAndroid Build Coastguard Worker // context as a post-pass.
UpdateThumbVFPPredicate(MCInst & MI) const676*9880d681SAndroid Build Coastguard Worker void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const {
677*9880d681SAndroid Build Coastguard Worker   unsigned CC;
678*9880d681SAndroid Build Coastguard Worker   CC = ITBlock.getITCC();
679*9880d681SAndroid Build Coastguard Worker   if (ITBlock.instrInITBlock())
680*9880d681SAndroid Build Coastguard Worker     ITBlock.advanceITState();
681*9880d681SAndroid Build Coastguard Worker 
682*9880d681SAndroid Build Coastguard Worker   const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
683*9880d681SAndroid Build Coastguard Worker   MCInst::iterator I = MI.begin();
684*9880d681SAndroid Build Coastguard Worker   unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
685*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumOps; ++i, ++I) {
686*9880d681SAndroid Build Coastguard Worker     if (OpInfo[i].isPredicate() ) {
687*9880d681SAndroid Build Coastguard Worker       I->setImm(CC);
688*9880d681SAndroid Build Coastguard Worker       ++I;
689*9880d681SAndroid Build Coastguard Worker       if (CC == ARMCC::AL)
690*9880d681SAndroid Build Coastguard Worker         I->setReg(0);
691*9880d681SAndroid Build Coastguard Worker       else
692*9880d681SAndroid Build Coastguard Worker         I->setReg(ARM::CPSR);
693*9880d681SAndroid Build Coastguard Worker       return;
694*9880d681SAndroid Build Coastguard Worker     }
695*9880d681SAndroid Build Coastguard Worker   }
696*9880d681SAndroid Build Coastguard Worker }
697*9880d681SAndroid Build Coastguard Worker 
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & OS,raw_ostream & CS) const698*9880d681SAndroid Build Coastguard Worker DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
699*9880d681SAndroid Build Coastguard Worker                                                ArrayRef<uint8_t> Bytes,
700*9880d681SAndroid Build Coastguard Worker                                                uint64_t Address,
701*9880d681SAndroid Build Coastguard Worker                                                raw_ostream &OS,
702*9880d681SAndroid Build Coastguard Worker                                                raw_ostream &CS) const {
703*9880d681SAndroid Build Coastguard Worker   CommentStream = &CS;
704*9880d681SAndroid Build Coastguard Worker 
705*9880d681SAndroid Build Coastguard Worker   assert(STI.getFeatureBits()[ARM::ModeThumb] &&
706*9880d681SAndroid Build Coastguard Worker          "Asked to disassemble in Thumb mode but Subtarget is in ARM mode!");
707*9880d681SAndroid Build Coastguard Worker 
708*9880d681SAndroid Build Coastguard Worker   // We want to read exactly 2 bytes of data.
709*9880d681SAndroid Build Coastguard Worker   if (Bytes.size() < 2) {
710*9880d681SAndroid Build Coastguard Worker     Size = 0;
711*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
712*9880d681SAndroid Build Coastguard Worker   }
713*9880d681SAndroid Build Coastguard Worker 
714*9880d681SAndroid Build Coastguard Worker   uint16_t Insn16 = (Bytes[1] << 8) | Bytes[0];
715*9880d681SAndroid Build Coastguard Worker   DecodeStatus Result =
716*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTableThumb16, MI, Insn16, Address, this, STI);
717*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
718*9880d681SAndroid Build Coastguard Worker     Size = 2;
719*9880d681SAndroid Build Coastguard Worker     Check(Result, AddThumbPredicate(MI));
720*9880d681SAndroid Build Coastguard Worker     return Result;
721*9880d681SAndroid Build Coastguard Worker   }
722*9880d681SAndroid Build Coastguard Worker 
723*9880d681SAndroid Build Coastguard Worker   Result = decodeInstruction(DecoderTableThumbSBit16, MI, Insn16, Address, this,
724*9880d681SAndroid Build Coastguard Worker                              STI);
725*9880d681SAndroid Build Coastguard Worker   if (Result) {
726*9880d681SAndroid Build Coastguard Worker     Size = 2;
727*9880d681SAndroid Build Coastguard Worker     bool InITBlock = ITBlock.instrInITBlock();
728*9880d681SAndroid Build Coastguard Worker     Check(Result, AddThumbPredicate(MI));
729*9880d681SAndroid Build Coastguard Worker     AddThumb1SBit(MI, InITBlock);
730*9880d681SAndroid Build Coastguard Worker     return Result;
731*9880d681SAndroid Build Coastguard Worker   }
732*9880d681SAndroid Build Coastguard Worker 
733*9880d681SAndroid Build Coastguard Worker   Result =
734*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTableThumb216, MI, Insn16, Address, this, STI);
735*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
736*9880d681SAndroid Build Coastguard Worker     Size = 2;
737*9880d681SAndroid Build Coastguard Worker 
738*9880d681SAndroid Build Coastguard Worker     // Nested IT blocks are UNPREDICTABLE.  Must be checked before we add
739*9880d681SAndroid Build Coastguard Worker     // the Thumb predicate.
740*9880d681SAndroid Build Coastguard Worker     if (MI.getOpcode() == ARM::t2IT && ITBlock.instrInITBlock())
741*9880d681SAndroid Build Coastguard Worker       Result = MCDisassembler::SoftFail;
742*9880d681SAndroid Build Coastguard Worker 
743*9880d681SAndroid Build Coastguard Worker     Check(Result, AddThumbPredicate(MI));
744*9880d681SAndroid Build Coastguard Worker 
745*9880d681SAndroid Build Coastguard Worker     // If we find an IT instruction, we need to parse its condition
746*9880d681SAndroid Build Coastguard Worker     // code and mask operands so that we can apply them correctly
747*9880d681SAndroid Build Coastguard Worker     // to the subsequent instructions.
748*9880d681SAndroid Build Coastguard Worker     if (MI.getOpcode() == ARM::t2IT) {
749*9880d681SAndroid Build Coastguard Worker 
750*9880d681SAndroid Build Coastguard Worker       unsigned Firstcond = MI.getOperand(0).getImm();
751*9880d681SAndroid Build Coastguard Worker       unsigned Mask = MI.getOperand(1).getImm();
752*9880d681SAndroid Build Coastguard Worker       ITBlock.setITState(Firstcond, Mask);
753*9880d681SAndroid Build Coastguard Worker     }
754*9880d681SAndroid Build Coastguard Worker 
755*9880d681SAndroid Build Coastguard Worker     return Result;
756*9880d681SAndroid Build Coastguard Worker   }
757*9880d681SAndroid Build Coastguard Worker 
758*9880d681SAndroid Build Coastguard Worker   // We want to read exactly 4 bytes of data.
759*9880d681SAndroid Build Coastguard Worker   if (Bytes.size() < 4) {
760*9880d681SAndroid Build Coastguard Worker     Size = 0;
761*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
762*9880d681SAndroid Build Coastguard Worker   }
763*9880d681SAndroid Build Coastguard Worker 
764*9880d681SAndroid Build Coastguard Worker   uint32_t Insn32 =
765*9880d681SAndroid Build Coastguard Worker       (Bytes[3] << 8) | (Bytes[2] << 0) | (Bytes[1] << 24) | (Bytes[0] << 16);
766*9880d681SAndroid Build Coastguard Worker   Result =
767*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTableThumb32, MI, Insn32, Address, this, STI);
768*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
769*9880d681SAndroid Build Coastguard Worker     Size = 4;
770*9880d681SAndroid Build Coastguard Worker     bool InITBlock = ITBlock.instrInITBlock();
771*9880d681SAndroid Build Coastguard Worker     Check(Result, AddThumbPredicate(MI));
772*9880d681SAndroid Build Coastguard Worker     AddThumb1SBit(MI, InITBlock);
773*9880d681SAndroid Build Coastguard Worker     return Result;
774*9880d681SAndroid Build Coastguard Worker   }
775*9880d681SAndroid Build Coastguard Worker 
776*9880d681SAndroid Build Coastguard Worker   Result =
777*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTableThumb232, MI, Insn32, Address, this, STI);
778*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
779*9880d681SAndroid Build Coastguard Worker     Size = 4;
780*9880d681SAndroid Build Coastguard Worker     Check(Result, AddThumbPredicate(MI));
781*9880d681SAndroid Build Coastguard Worker     return Result;
782*9880d681SAndroid Build Coastguard Worker   }
783*9880d681SAndroid Build Coastguard Worker 
784*9880d681SAndroid Build Coastguard Worker   if (fieldFromInstruction(Insn32, 28, 4) == 0xE) {
785*9880d681SAndroid Build Coastguard Worker     Result =
786*9880d681SAndroid Build Coastguard Worker         decodeInstruction(DecoderTableVFP32, MI, Insn32, Address, this, STI);
787*9880d681SAndroid Build Coastguard Worker     if (Result != MCDisassembler::Fail) {
788*9880d681SAndroid Build Coastguard Worker       Size = 4;
789*9880d681SAndroid Build Coastguard Worker       UpdateThumbVFPPredicate(MI);
790*9880d681SAndroid Build Coastguard Worker       return Result;
791*9880d681SAndroid Build Coastguard Worker     }
792*9880d681SAndroid Build Coastguard Worker   }
793*9880d681SAndroid Build Coastguard Worker 
794*9880d681SAndroid Build Coastguard Worker   Result =
795*9880d681SAndroid Build Coastguard Worker       decodeInstruction(DecoderTableVFPV832, MI, Insn32, Address, this, STI);
796*9880d681SAndroid Build Coastguard Worker   if (Result != MCDisassembler::Fail) {
797*9880d681SAndroid Build Coastguard Worker     Size = 4;
798*9880d681SAndroid Build Coastguard Worker     return Result;
799*9880d681SAndroid Build Coastguard Worker   }
800*9880d681SAndroid Build Coastguard Worker 
801*9880d681SAndroid Build Coastguard Worker   if (fieldFromInstruction(Insn32, 28, 4) == 0xE) {
802*9880d681SAndroid Build Coastguard Worker     Result = decodeInstruction(DecoderTableNEONDup32, MI, Insn32, Address, this,
803*9880d681SAndroid Build Coastguard Worker                                STI);
804*9880d681SAndroid Build Coastguard Worker     if (Result != MCDisassembler::Fail) {
805*9880d681SAndroid Build Coastguard Worker       Size = 4;
806*9880d681SAndroid Build Coastguard Worker       Check(Result, AddThumbPredicate(MI));
807*9880d681SAndroid Build Coastguard Worker       return Result;
808*9880d681SAndroid Build Coastguard Worker     }
809*9880d681SAndroid Build Coastguard Worker   }
810*9880d681SAndroid Build Coastguard Worker 
811*9880d681SAndroid Build Coastguard Worker   if (fieldFromInstruction(Insn32, 24, 8) == 0xF9) {
812*9880d681SAndroid Build Coastguard Worker     uint32_t NEONLdStInsn = Insn32;
813*9880d681SAndroid Build Coastguard Worker     NEONLdStInsn &= 0xF0FFFFFF;
814*9880d681SAndroid Build Coastguard Worker     NEONLdStInsn |= 0x04000000;
815*9880d681SAndroid Build Coastguard Worker     Result = decodeInstruction(DecoderTableNEONLoadStore32, MI, NEONLdStInsn,
816*9880d681SAndroid Build Coastguard Worker                                Address, this, STI);
817*9880d681SAndroid Build Coastguard Worker     if (Result != MCDisassembler::Fail) {
818*9880d681SAndroid Build Coastguard Worker       Size = 4;
819*9880d681SAndroid Build Coastguard Worker       Check(Result, AddThumbPredicate(MI));
820*9880d681SAndroid Build Coastguard Worker       return Result;
821*9880d681SAndroid Build Coastguard Worker     }
822*9880d681SAndroid Build Coastguard Worker   }
823*9880d681SAndroid Build Coastguard Worker 
824*9880d681SAndroid Build Coastguard Worker   if (fieldFromInstruction(Insn32, 24, 4) == 0xF) {
825*9880d681SAndroid Build Coastguard Worker     uint32_t NEONDataInsn = Insn32;
826*9880d681SAndroid Build Coastguard Worker     NEONDataInsn &= 0xF0FFFFFF; // Clear bits 27-24
827*9880d681SAndroid Build Coastguard Worker     NEONDataInsn |= (NEONDataInsn & 0x10000000) >> 4; // Move bit 28 to bit 24
828*9880d681SAndroid Build Coastguard Worker     NEONDataInsn |= 0x12000000; // Set bits 28 and 25
829*9880d681SAndroid Build Coastguard Worker     Result = decodeInstruction(DecoderTableNEONData32, MI, NEONDataInsn,
830*9880d681SAndroid Build Coastguard Worker                                Address, this, STI);
831*9880d681SAndroid Build Coastguard Worker     if (Result != MCDisassembler::Fail) {
832*9880d681SAndroid Build Coastguard Worker       Size = 4;
833*9880d681SAndroid Build Coastguard Worker       Check(Result, AddThumbPredicate(MI));
834*9880d681SAndroid Build Coastguard Worker       return Result;
835*9880d681SAndroid Build Coastguard Worker     }
836*9880d681SAndroid Build Coastguard Worker 
837*9880d681SAndroid Build Coastguard Worker     uint32_t NEONCryptoInsn = Insn32;
838*9880d681SAndroid Build Coastguard Worker     NEONCryptoInsn &= 0xF0FFFFFF; // Clear bits 27-24
839*9880d681SAndroid Build Coastguard Worker     NEONCryptoInsn |= (NEONCryptoInsn & 0x10000000) >> 4; // Move bit 28 to bit 24
840*9880d681SAndroid Build Coastguard Worker     NEONCryptoInsn |= 0x12000000; // Set bits 28 and 25
841*9880d681SAndroid Build Coastguard Worker     Result = decodeInstruction(DecoderTablev8Crypto32, MI, NEONCryptoInsn,
842*9880d681SAndroid Build Coastguard Worker                                Address, this, STI);
843*9880d681SAndroid Build Coastguard Worker     if (Result != MCDisassembler::Fail) {
844*9880d681SAndroid Build Coastguard Worker       Size = 4;
845*9880d681SAndroid Build Coastguard Worker       return Result;
846*9880d681SAndroid Build Coastguard Worker     }
847*9880d681SAndroid Build Coastguard Worker 
848*9880d681SAndroid Build Coastguard Worker     uint32_t NEONv8Insn = Insn32;
849*9880d681SAndroid Build Coastguard Worker     NEONv8Insn &= 0xF3FFFFFF; // Clear bits 27-26
850*9880d681SAndroid Build Coastguard Worker     Result = decodeInstruction(DecoderTablev8NEON32, MI, NEONv8Insn, Address,
851*9880d681SAndroid Build Coastguard Worker                                this, STI);
852*9880d681SAndroid Build Coastguard Worker     if (Result != MCDisassembler::Fail) {
853*9880d681SAndroid Build Coastguard Worker       Size = 4;
854*9880d681SAndroid Build Coastguard Worker       return Result;
855*9880d681SAndroid Build Coastguard Worker     }
856*9880d681SAndroid Build Coastguard Worker   }
857*9880d681SAndroid Build Coastguard Worker 
858*9880d681SAndroid Build Coastguard Worker   Size = 0;
859*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Fail;
860*9880d681SAndroid Build Coastguard Worker }
861*9880d681SAndroid Build Coastguard Worker 
862*9880d681SAndroid Build Coastguard Worker 
LLVMInitializeARMDisassembler()863*9880d681SAndroid Build Coastguard Worker extern "C" void LLVMInitializeARMDisassembler() {
864*9880d681SAndroid Build Coastguard Worker   TargetRegistry::RegisterMCDisassembler(TheARMLETarget,
865*9880d681SAndroid Build Coastguard Worker                                          createARMDisassembler);
866*9880d681SAndroid Build Coastguard Worker   TargetRegistry::RegisterMCDisassembler(TheARMBETarget,
867*9880d681SAndroid Build Coastguard Worker                                          createARMDisassembler);
868*9880d681SAndroid Build Coastguard Worker   TargetRegistry::RegisterMCDisassembler(TheThumbLETarget,
869*9880d681SAndroid Build Coastguard Worker                                          createThumbDisassembler);
870*9880d681SAndroid Build Coastguard Worker   TargetRegistry::RegisterMCDisassembler(TheThumbBETarget,
871*9880d681SAndroid Build Coastguard Worker                                          createThumbDisassembler);
872*9880d681SAndroid Build Coastguard Worker }
873*9880d681SAndroid Build Coastguard Worker 
874*9880d681SAndroid Build Coastguard Worker static const uint16_t GPRDecoderTable[] = {
875*9880d681SAndroid Build Coastguard Worker   ARM::R0, ARM::R1, ARM::R2, ARM::R3,
876*9880d681SAndroid Build Coastguard Worker   ARM::R4, ARM::R5, ARM::R6, ARM::R7,
877*9880d681SAndroid Build Coastguard Worker   ARM::R8, ARM::R9, ARM::R10, ARM::R11,
878*9880d681SAndroid Build Coastguard Worker   ARM::R12, ARM::SP, ARM::LR, ARM::PC
879*9880d681SAndroid Build Coastguard Worker };
880*9880d681SAndroid Build Coastguard Worker 
DecodeGPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)881*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
882*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
883*9880d681SAndroid Build Coastguard Worker   if (RegNo > 15)
884*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
885*9880d681SAndroid Build Coastguard Worker 
886*9880d681SAndroid Build Coastguard Worker   unsigned Register = GPRDecoderTable[RegNo];
887*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(Register));
888*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
889*9880d681SAndroid Build Coastguard Worker }
890*9880d681SAndroid Build Coastguard Worker 
891*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeGPRnopcRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)892*9880d681SAndroid Build Coastguard Worker DecodeGPRnopcRegisterClass(MCInst &Inst, unsigned RegNo,
893*9880d681SAndroid Build Coastguard Worker                            uint64_t Address, const void *Decoder) {
894*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
895*9880d681SAndroid Build Coastguard Worker 
896*9880d681SAndroid Build Coastguard Worker   if (RegNo == 15)
897*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
898*9880d681SAndroid Build Coastguard Worker 
899*9880d681SAndroid Build Coastguard Worker   Check(S, DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder));
900*9880d681SAndroid Build Coastguard Worker 
901*9880d681SAndroid Build Coastguard Worker   return S;
902*9880d681SAndroid Build Coastguard Worker }
903*9880d681SAndroid Build Coastguard Worker 
904*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeGPRwithAPSRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)905*9880d681SAndroid Build Coastguard Worker DecodeGPRwithAPSRRegisterClass(MCInst &Inst, unsigned RegNo,
906*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
907*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
908*9880d681SAndroid Build Coastguard Worker 
909*9880d681SAndroid Build Coastguard Worker   if (RegNo == 15)
910*9880d681SAndroid Build Coastguard Worker   {
911*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(ARM::APSR_NZCV));
912*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Success;
913*9880d681SAndroid Build Coastguard Worker   }
914*9880d681SAndroid Build Coastguard Worker 
915*9880d681SAndroid Build Coastguard Worker   Check(S, DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder));
916*9880d681SAndroid Build Coastguard Worker   return S;
917*9880d681SAndroid Build Coastguard Worker }
918*9880d681SAndroid Build Coastguard Worker 
DecodetGPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)919*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodetGPRRegisterClass(MCInst &Inst, unsigned RegNo,
920*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
921*9880d681SAndroid Build Coastguard Worker   if (RegNo > 7)
922*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
923*9880d681SAndroid Build Coastguard Worker   return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
924*9880d681SAndroid Build Coastguard Worker }
925*9880d681SAndroid Build Coastguard Worker 
926*9880d681SAndroid Build Coastguard Worker static const uint16_t GPRPairDecoderTable[] = {
927*9880d681SAndroid Build Coastguard Worker   ARM::R0_R1, ARM::R2_R3,   ARM::R4_R5,  ARM::R6_R7,
928*9880d681SAndroid Build Coastguard Worker   ARM::R8_R9, ARM::R10_R11, ARM::R12_SP
929*9880d681SAndroid Build Coastguard Worker };
930*9880d681SAndroid Build Coastguard Worker 
DecodeGPRPairRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)931*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo,
932*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
933*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
934*9880d681SAndroid Build Coastguard Worker 
935*9880d681SAndroid Build Coastguard Worker   if (RegNo > 13)
936*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
937*9880d681SAndroid Build Coastguard Worker 
938*9880d681SAndroid Build Coastguard Worker   if ((RegNo & 1) || RegNo == 0xe)
939*9880d681SAndroid Build Coastguard Worker      S = MCDisassembler::SoftFail;
940*9880d681SAndroid Build Coastguard Worker 
941*9880d681SAndroid Build Coastguard Worker   unsigned RegisterPair = GPRPairDecoderTable[RegNo/2];
942*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(RegisterPair));
943*9880d681SAndroid Build Coastguard Worker   return S;
944*9880d681SAndroid Build Coastguard Worker }
945*9880d681SAndroid Build Coastguard Worker 
DecodetcGPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)946*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo,
947*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
948*9880d681SAndroid Build Coastguard Worker   unsigned Register = 0;
949*9880d681SAndroid Build Coastguard Worker   switch (RegNo) {
950*9880d681SAndroid Build Coastguard Worker     case 0:
951*9880d681SAndroid Build Coastguard Worker       Register = ARM::R0;
952*9880d681SAndroid Build Coastguard Worker       break;
953*9880d681SAndroid Build Coastguard Worker     case 1:
954*9880d681SAndroid Build Coastguard Worker       Register = ARM::R1;
955*9880d681SAndroid Build Coastguard Worker       break;
956*9880d681SAndroid Build Coastguard Worker     case 2:
957*9880d681SAndroid Build Coastguard Worker       Register = ARM::R2;
958*9880d681SAndroid Build Coastguard Worker       break;
959*9880d681SAndroid Build Coastguard Worker     case 3:
960*9880d681SAndroid Build Coastguard Worker       Register = ARM::R3;
961*9880d681SAndroid Build Coastguard Worker       break;
962*9880d681SAndroid Build Coastguard Worker     case 9:
963*9880d681SAndroid Build Coastguard Worker       Register = ARM::R9;
964*9880d681SAndroid Build Coastguard Worker       break;
965*9880d681SAndroid Build Coastguard Worker     case 12:
966*9880d681SAndroid Build Coastguard Worker       Register = ARM::R12;
967*9880d681SAndroid Build Coastguard Worker       break;
968*9880d681SAndroid Build Coastguard Worker     default:
969*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
970*9880d681SAndroid Build Coastguard Worker     }
971*9880d681SAndroid Build Coastguard Worker 
972*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(Register));
973*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
974*9880d681SAndroid Build Coastguard Worker }
975*9880d681SAndroid Build Coastguard Worker 
DecoderGPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)976*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecoderGPRRegisterClass(MCInst &Inst, unsigned RegNo,
977*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
978*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
979*9880d681SAndroid Build Coastguard Worker 
980*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
981*9880d681SAndroid Build Coastguard Worker     ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
982*9880d681SAndroid Build Coastguard Worker 
983*9880d681SAndroid Build Coastguard Worker   if ((RegNo == 13 && !featureBits[ARM::HasV8Ops]) || RegNo == 15)
984*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
985*9880d681SAndroid Build Coastguard Worker 
986*9880d681SAndroid Build Coastguard Worker   Check(S, DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder));
987*9880d681SAndroid Build Coastguard Worker   return S;
988*9880d681SAndroid Build Coastguard Worker }
989*9880d681SAndroid Build Coastguard Worker 
990*9880d681SAndroid Build Coastguard Worker static const uint16_t SPRDecoderTable[] = {
991*9880d681SAndroid Build Coastguard Worker      ARM::S0,  ARM::S1,  ARM::S2,  ARM::S3,
992*9880d681SAndroid Build Coastguard Worker      ARM::S4,  ARM::S5,  ARM::S6,  ARM::S7,
993*9880d681SAndroid Build Coastguard Worker      ARM::S8,  ARM::S9, ARM::S10, ARM::S11,
994*9880d681SAndroid Build Coastguard Worker     ARM::S12, ARM::S13, ARM::S14, ARM::S15,
995*9880d681SAndroid Build Coastguard Worker     ARM::S16, ARM::S17, ARM::S18, ARM::S19,
996*9880d681SAndroid Build Coastguard Worker     ARM::S20, ARM::S21, ARM::S22, ARM::S23,
997*9880d681SAndroid Build Coastguard Worker     ARM::S24, ARM::S25, ARM::S26, ARM::S27,
998*9880d681SAndroid Build Coastguard Worker     ARM::S28, ARM::S29, ARM::S30, ARM::S31
999*9880d681SAndroid Build Coastguard Worker };
1000*9880d681SAndroid Build Coastguard Worker 
DecodeSPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)1001*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSPRRegisterClass(MCInst &Inst, unsigned RegNo,
1002*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
1003*9880d681SAndroid Build Coastguard Worker   if (RegNo > 31)
1004*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1005*9880d681SAndroid Build Coastguard Worker 
1006*9880d681SAndroid Build Coastguard Worker   unsigned Register = SPRDecoderTable[RegNo];
1007*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(Register));
1008*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
1009*9880d681SAndroid Build Coastguard Worker }
1010*9880d681SAndroid Build Coastguard Worker 
1011*9880d681SAndroid Build Coastguard Worker static const uint16_t DPRDecoderTable[] = {
1012*9880d681SAndroid Build Coastguard Worker      ARM::D0,  ARM::D1,  ARM::D2,  ARM::D3,
1013*9880d681SAndroid Build Coastguard Worker      ARM::D4,  ARM::D5,  ARM::D6,  ARM::D7,
1014*9880d681SAndroid Build Coastguard Worker      ARM::D8,  ARM::D9, ARM::D10, ARM::D11,
1015*9880d681SAndroid Build Coastguard Worker     ARM::D12, ARM::D13, ARM::D14, ARM::D15,
1016*9880d681SAndroid Build Coastguard Worker     ARM::D16, ARM::D17, ARM::D18, ARM::D19,
1017*9880d681SAndroid Build Coastguard Worker     ARM::D20, ARM::D21, ARM::D22, ARM::D23,
1018*9880d681SAndroid Build Coastguard Worker     ARM::D24, ARM::D25, ARM::D26, ARM::D27,
1019*9880d681SAndroid Build Coastguard Worker     ARM::D28, ARM::D29, ARM::D30, ARM::D31
1020*9880d681SAndroid Build Coastguard Worker };
1021*9880d681SAndroid Build Coastguard Worker 
DecodeDPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)1022*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPRRegisterClass(MCInst &Inst, unsigned RegNo,
1023*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
1024*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
1025*9880d681SAndroid Build Coastguard Worker     ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
1026*9880d681SAndroid Build Coastguard Worker 
1027*9880d681SAndroid Build Coastguard Worker   bool hasD16 = featureBits[ARM::FeatureD16];
1028*9880d681SAndroid Build Coastguard Worker 
1029*9880d681SAndroid Build Coastguard Worker   if (RegNo > 31 || (hasD16 && RegNo > 15))
1030*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1031*9880d681SAndroid Build Coastguard Worker 
1032*9880d681SAndroid Build Coastguard Worker   unsigned Register = DPRDecoderTable[RegNo];
1033*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(Register));
1034*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
1035*9880d681SAndroid Build Coastguard Worker }
1036*9880d681SAndroid Build Coastguard Worker 
DecodeDPR_8RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)1037*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPR_8RegisterClass(MCInst &Inst, unsigned RegNo,
1038*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
1039*9880d681SAndroid Build Coastguard Worker   if (RegNo > 7)
1040*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1041*9880d681SAndroid Build Coastguard Worker   return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
1042*9880d681SAndroid Build Coastguard Worker }
1043*9880d681SAndroid Build Coastguard Worker 
1044*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeDPR_VFP2RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)1045*9880d681SAndroid Build Coastguard Worker DecodeDPR_VFP2RegisterClass(MCInst &Inst, unsigned RegNo,
1046*9880d681SAndroid Build Coastguard Worker                             uint64_t Address, const void *Decoder) {
1047*9880d681SAndroid Build Coastguard Worker   if (RegNo > 15)
1048*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1049*9880d681SAndroid Build Coastguard Worker   return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
1050*9880d681SAndroid Build Coastguard Worker }
1051*9880d681SAndroid Build Coastguard Worker 
1052*9880d681SAndroid Build Coastguard Worker static const uint16_t QPRDecoderTable[] = {
1053*9880d681SAndroid Build Coastguard Worker      ARM::Q0,  ARM::Q1,  ARM::Q2,  ARM::Q3,
1054*9880d681SAndroid Build Coastguard Worker      ARM::Q4,  ARM::Q5,  ARM::Q6,  ARM::Q7,
1055*9880d681SAndroid Build Coastguard Worker      ARM::Q8,  ARM::Q9, ARM::Q10, ARM::Q11,
1056*9880d681SAndroid Build Coastguard Worker     ARM::Q12, ARM::Q13, ARM::Q14, ARM::Q15
1057*9880d681SAndroid Build Coastguard Worker };
1058*9880d681SAndroid Build Coastguard Worker 
1059*9880d681SAndroid Build Coastguard Worker 
DecodeQPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)1060*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeQPRRegisterClass(MCInst &Inst, unsigned RegNo,
1061*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
1062*9880d681SAndroid Build Coastguard Worker   if (RegNo > 31 || (RegNo & 1) != 0)
1063*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1064*9880d681SAndroid Build Coastguard Worker   RegNo >>= 1;
1065*9880d681SAndroid Build Coastguard Worker 
1066*9880d681SAndroid Build Coastguard Worker   unsigned Register = QPRDecoderTable[RegNo];
1067*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(Register));
1068*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
1069*9880d681SAndroid Build Coastguard Worker }
1070*9880d681SAndroid Build Coastguard Worker 
1071*9880d681SAndroid Build Coastguard Worker static const uint16_t DPairDecoderTable[] = {
1072*9880d681SAndroid Build Coastguard Worker   ARM::Q0,  ARM::D1_D2,   ARM::Q1,  ARM::D3_D4,   ARM::Q2,  ARM::D5_D6,
1073*9880d681SAndroid Build Coastguard Worker   ARM::Q3,  ARM::D7_D8,   ARM::Q4,  ARM::D9_D10,  ARM::Q5,  ARM::D11_D12,
1074*9880d681SAndroid Build Coastguard Worker   ARM::Q6,  ARM::D13_D14, ARM::Q7,  ARM::D15_D16, ARM::Q8,  ARM::D17_D18,
1075*9880d681SAndroid Build Coastguard Worker   ARM::Q9,  ARM::D19_D20, ARM::Q10, ARM::D21_D22, ARM::Q11, ARM::D23_D24,
1076*9880d681SAndroid Build Coastguard Worker   ARM::Q12, ARM::D25_D26, ARM::Q13, ARM::D27_D28, ARM::Q14, ARM::D29_D30,
1077*9880d681SAndroid Build Coastguard Worker   ARM::Q15
1078*9880d681SAndroid Build Coastguard Worker };
1079*9880d681SAndroid Build Coastguard Worker 
DecodeDPairRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)1080*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPairRegisterClass(MCInst &Inst, unsigned RegNo,
1081*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
1082*9880d681SAndroid Build Coastguard Worker   if (RegNo > 30)
1083*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1084*9880d681SAndroid Build Coastguard Worker 
1085*9880d681SAndroid Build Coastguard Worker   unsigned Register = DPairDecoderTable[RegNo];
1086*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(Register));
1087*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
1088*9880d681SAndroid Build Coastguard Worker }
1089*9880d681SAndroid Build Coastguard Worker 
1090*9880d681SAndroid Build Coastguard Worker static const uint16_t DPairSpacedDecoderTable[] = {
1091*9880d681SAndroid Build Coastguard Worker   ARM::D0_D2,   ARM::D1_D3,   ARM::D2_D4,   ARM::D3_D5,
1092*9880d681SAndroid Build Coastguard Worker   ARM::D4_D6,   ARM::D5_D7,   ARM::D6_D8,   ARM::D7_D9,
1093*9880d681SAndroid Build Coastguard Worker   ARM::D8_D10,  ARM::D9_D11,  ARM::D10_D12, ARM::D11_D13,
1094*9880d681SAndroid Build Coastguard Worker   ARM::D12_D14, ARM::D13_D15, ARM::D14_D16, ARM::D15_D17,
1095*9880d681SAndroid Build Coastguard Worker   ARM::D16_D18, ARM::D17_D19, ARM::D18_D20, ARM::D19_D21,
1096*9880d681SAndroid Build Coastguard Worker   ARM::D20_D22, ARM::D21_D23, ARM::D22_D24, ARM::D23_D25,
1097*9880d681SAndroid Build Coastguard Worker   ARM::D24_D26, ARM::D25_D27, ARM::D26_D28, ARM::D27_D29,
1098*9880d681SAndroid Build Coastguard Worker   ARM::D28_D30, ARM::D29_D31
1099*9880d681SAndroid Build Coastguard Worker };
1100*9880d681SAndroid Build Coastguard Worker 
DecodeDPairSpacedRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)1101*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPairSpacedRegisterClass(MCInst &Inst,
1102*9880d681SAndroid Build Coastguard Worker                                                    unsigned RegNo,
1103*9880d681SAndroid Build Coastguard Worker                                                    uint64_t Address,
1104*9880d681SAndroid Build Coastguard Worker                                                    const void *Decoder) {
1105*9880d681SAndroid Build Coastguard Worker   if (RegNo > 29)
1106*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1107*9880d681SAndroid Build Coastguard Worker 
1108*9880d681SAndroid Build Coastguard Worker   unsigned Register = DPairSpacedDecoderTable[RegNo];
1109*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(Register));
1110*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
1111*9880d681SAndroid Build Coastguard Worker }
1112*9880d681SAndroid Build Coastguard Worker 
DecodePredicateOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)1113*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val,
1114*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
1115*9880d681SAndroid Build Coastguard Worker   if (Val == 0xF) return MCDisassembler::Fail;
1116*9880d681SAndroid Build Coastguard Worker   // AL predicate is not allowed on Thumb1 branches.
1117*9880d681SAndroid Build Coastguard Worker   if (Inst.getOpcode() == ARM::tBcc && Val == 0xE)
1118*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1119*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Val));
1120*9880d681SAndroid Build Coastguard Worker   if (Val == ARMCC::AL) {
1121*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(0));
1122*9880d681SAndroid Build Coastguard Worker   } else
1123*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(ARM::CPSR));
1124*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
1125*9880d681SAndroid Build Coastguard Worker }
1126*9880d681SAndroid Build Coastguard Worker 
DecodeCCOutOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)1127*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val,
1128*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
1129*9880d681SAndroid Build Coastguard Worker   if (Val)
1130*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(ARM::CPSR));
1131*9880d681SAndroid Build Coastguard Worker   else
1132*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(0));
1133*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
1134*9880d681SAndroid Build Coastguard Worker }
1135*9880d681SAndroid Build Coastguard Worker 
DecodeSORegImmOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)1136*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Val,
1137*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
1138*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1139*9880d681SAndroid Build Coastguard Worker 
1140*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Val, 0, 4);
1141*9880d681SAndroid Build Coastguard Worker   unsigned type = fieldFromInstruction(Val, 5, 2);
1142*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 7, 5);
1143*9880d681SAndroid Build Coastguard Worker 
1144*9880d681SAndroid Build Coastguard Worker   // Register-immediate
1145*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
1146*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1147*9880d681SAndroid Build Coastguard Worker 
1148*9880d681SAndroid Build Coastguard Worker   ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
1149*9880d681SAndroid Build Coastguard Worker   switch (type) {
1150*9880d681SAndroid Build Coastguard Worker     case 0:
1151*9880d681SAndroid Build Coastguard Worker       Shift = ARM_AM::lsl;
1152*9880d681SAndroid Build Coastguard Worker       break;
1153*9880d681SAndroid Build Coastguard Worker     case 1:
1154*9880d681SAndroid Build Coastguard Worker       Shift = ARM_AM::lsr;
1155*9880d681SAndroid Build Coastguard Worker       break;
1156*9880d681SAndroid Build Coastguard Worker     case 2:
1157*9880d681SAndroid Build Coastguard Worker       Shift = ARM_AM::asr;
1158*9880d681SAndroid Build Coastguard Worker       break;
1159*9880d681SAndroid Build Coastguard Worker     case 3:
1160*9880d681SAndroid Build Coastguard Worker       Shift = ARM_AM::ror;
1161*9880d681SAndroid Build Coastguard Worker       break;
1162*9880d681SAndroid Build Coastguard Worker   }
1163*9880d681SAndroid Build Coastguard Worker 
1164*9880d681SAndroid Build Coastguard Worker   if (Shift == ARM_AM::ror && imm == 0)
1165*9880d681SAndroid Build Coastguard Worker     Shift = ARM_AM::rrx;
1166*9880d681SAndroid Build Coastguard Worker 
1167*9880d681SAndroid Build Coastguard Worker   unsigned Op = Shift | (imm << 3);
1168*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Op));
1169*9880d681SAndroid Build Coastguard Worker 
1170*9880d681SAndroid Build Coastguard Worker   return S;
1171*9880d681SAndroid Build Coastguard Worker }
1172*9880d681SAndroid Build Coastguard Worker 
DecodeSORegRegOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)1173*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSORegRegOperand(MCInst &Inst, unsigned Val,
1174*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
1175*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1176*9880d681SAndroid Build Coastguard Worker 
1177*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Val, 0, 4);
1178*9880d681SAndroid Build Coastguard Worker   unsigned type = fieldFromInstruction(Val, 5, 2);
1179*9880d681SAndroid Build Coastguard Worker   unsigned Rs = fieldFromInstruction(Val, 8, 4);
1180*9880d681SAndroid Build Coastguard Worker 
1181*9880d681SAndroid Build Coastguard Worker   // Register-register
1182*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)))
1183*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1184*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rs, Address, Decoder)))
1185*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1186*9880d681SAndroid Build Coastguard Worker 
1187*9880d681SAndroid Build Coastguard Worker   ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
1188*9880d681SAndroid Build Coastguard Worker   switch (type) {
1189*9880d681SAndroid Build Coastguard Worker     case 0:
1190*9880d681SAndroid Build Coastguard Worker       Shift = ARM_AM::lsl;
1191*9880d681SAndroid Build Coastguard Worker       break;
1192*9880d681SAndroid Build Coastguard Worker     case 1:
1193*9880d681SAndroid Build Coastguard Worker       Shift = ARM_AM::lsr;
1194*9880d681SAndroid Build Coastguard Worker       break;
1195*9880d681SAndroid Build Coastguard Worker     case 2:
1196*9880d681SAndroid Build Coastguard Worker       Shift = ARM_AM::asr;
1197*9880d681SAndroid Build Coastguard Worker       break;
1198*9880d681SAndroid Build Coastguard Worker     case 3:
1199*9880d681SAndroid Build Coastguard Worker       Shift = ARM_AM::ror;
1200*9880d681SAndroid Build Coastguard Worker       break;
1201*9880d681SAndroid Build Coastguard Worker   }
1202*9880d681SAndroid Build Coastguard Worker 
1203*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Shift));
1204*9880d681SAndroid Build Coastguard Worker 
1205*9880d681SAndroid Build Coastguard Worker   return S;
1206*9880d681SAndroid Build Coastguard Worker }
1207*9880d681SAndroid Build Coastguard Worker 
DecodeRegListOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)1208*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Val,
1209*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
1210*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1211*9880d681SAndroid Build Coastguard Worker 
1212*9880d681SAndroid Build Coastguard Worker   bool NeedDisjointWriteback = false;
1213*9880d681SAndroid Build Coastguard Worker   unsigned WritebackReg = 0;
1214*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
1215*9880d681SAndroid Build Coastguard Worker   default:
1216*9880d681SAndroid Build Coastguard Worker     break;
1217*9880d681SAndroid Build Coastguard Worker   case ARM::LDMIA_UPD:
1218*9880d681SAndroid Build Coastguard Worker   case ARM::LDMDB_UPD:
1219*9880d681SAndroid Build Coastguard Worker   case ARM::LDMIB_UPD:
1220*9880d681SAndroid Build Coastguard Worker   case ARM::LDMDA_UPD:
1221*9880d681SAndroid Build Coastguard Worker   case ARM::t2LDMIA_UPD:
1222*9880d681SAndroid Build Coastguard Worker   case ARM::t2LDMDB_UPD:
1223*9880d681SAndroid Build Coastguard Worker   case ARM::t2STMIA_UPD:
1224*9880d681SAndroid Build Coastguard Worker   case ARM::t2STMDB_UPD:
1225*9880d681SAndroid Build Coastguard Worker     NeedDisjointWriteback = true;
1226*9880d681SAndroid Build Coastguard Worker     WritebackReg = Inst.getOperand(0).getReg();
1227*9880d681SAndroid Build Coastguard Worker     break;
1228*9880d681SAndroid Build Coastguard Worker   }
1229*9880d681SAndroid Build Coastguard Worker 
1230*9880d681SAndroid Build Coastguard Worker   // Empty register lists are not allowed.
1231*9880d681SAndroid Build Coastguard Worker   if (Val == 0) return MCDisassembler::Fail;
1232*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < 16; ++i) {
1233*9880d681SAndroid Build Coastguard Worker     if (Val & (1 << i)) {
1234*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, i, Address, Decoder)))
1235*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1236*9880d681SAndroid Build Coastguard Worker       // Writeback not allowed if Rn is in the target list.
1237*9880d681SAndroid Build Coastguard Worker       if (NeedDisjointWriteback && WritebackReg == Inst.end()[-1].getReg())
1238*9880d681SAndroid Build Coastguard Worker         Check(S, MCDisassembler::SoftFail);
1239*9880d681SAndroid Build Coastguard Worker     }
1240*9880d681SAndroid Build Coastguard Worker   }
1241*9880d681SAndroid Build Coastguard Worker 
1242*9880d681SAndroid Build Coastguard Worker   return S;
1243*9880d681SAndroid Build Coastguard Worker }
1244*9880d681SAndroid Build Coastguard Worker 
DecodeSPRRegListOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)1245*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSPRRegListOperand(MCInst &Inst, unsigned Val,
1246*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
1247*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1248*9880d681SAndroid Build Coastguard Worker 
1249*9880d681SAndroid Build Coastguard Worker   unsigned Vd = fieldFromInstruction(Val, 8, 5);
1250*9880d681SAndroid Build Coastguard Worker   unsigned regs = fieldFromInstruction(Val, 0, 8);
1251*9880d681SAndroid Build Coastguard Worker 
1252*9880d681SAndroid Build Coastguard Worker   // In case of unpredictable encoding, tweak the operands.
1253*9880d681SAndroid Build Coastguard Worker   if (regs == 0 || (Vd + regs) > 32) {
1254*9880d681SAndroid Build Coastguard Worker     regs = Vd + regs > 32 ? 32 - Vd : regs;
1255*9880d681SAndroid Build Coastguard Worker     regs = std::max( 1u, regs);
1256*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
1257*9880d681SAndroid Build Coastguard Worker   }
1258*9880d681SAndroid Build Coastguard Worker 
1259*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeSPRRegisterClass(Inst, Vd, Address, Decoder)))
1260*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1261*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < (regs - 1); ++i) {
1262*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeSPRRegisterClass(Inst, ++Vd, Address, Decoder)))
1263*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
1264*9880d681SAndroid Build Coastguard Worker   }
1265*9880d681SAndroid Build Coastguard Worker 
1266*9880d681SAndroid Build Coastguard Worker   return S;
1267*9880d681SAndroid Build Coastguard Worker }
1268*9880d681SAndroid Build Coastguard Worker 
DecodeDPRRegListOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)1269*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDPRRegListOperand(MCInst &Inst, unsigned Val,
1270*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
1271*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1272*9880d681SAndroid Build Coastguard Worker 
1273*9880d681SAndroid Build Coastguard Worker   unsigned Vd = fieldFromInstruction(Val, 8, 5);
1274*9880d681SAndroid Build Coastguard Worker   unsigned regs = fieldFromInstruction(Val, 1, 7);
1275*9880d681SAndroid Build Coastguard Worker 
1276*9880d681SAndroid Build Coastguard Worker   // In case of unpredictable encoding, tweak the operands.
1277*9880d681SAndroid Build Coastguard Worker   if (regs == 0 || regs > 16 || (Vd + regs) > 32) {
1278*9880d681SAndroid Build Coastguard Worker     regs = Vd + regs > 32 ? 32 - Vd : regs;
1279*9880d681SAndroid Build Coastguard Worker     regs = std::max( 1u, regs);
1280*9880d681SAndroid Build Coastguard Worker     regs = std::min(16u, regs);
1281*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
1282*9880d681SAndroid Build Coastguard Worker   }
1283*9880d681SAndroid Build Coastguard Worker 
1284*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Vd, Address, Decoder)))
1285*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
1286*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < (regs - 1); ++i) {
1287*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPRRegisterClass(Inst, ++Vd, Address, Decoder)))
1288*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
1289*9880d681SAndroid Build Coastguard Worker   }
1290*9880d681SAndroid Build Coastguard Worker 
1291*9880d681SAndroid Build Coastguard Worker   return S;
1292*9880d681SAndroid Build Coastguard Worker }
1293*9880d681SAndroid Build Coastguard Worker 
DecodeBitfieldMaskOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)1294*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeBitfieldMaskOperand(MCInst &Inst, unsigned Val,
1295*9880d681SAndroid Build Coastguard Worker                                       uint64_t Address, const void *Decoder) {
1296*9880d681SAndroid Build Coastguard Worker   // This operand encodes a mask of contiguous zeros between a specified MSB
1297*9880d681SAndroid Build Coastguard Worker   // and LSB.  To decode it, we create the mask of all bits MSB-and-lower,
1298*9880d681SAndroid Build Coastguard Worker   // the mask of all bits LSB-and-lower, and then xor them to create
1299*9880d681SAndroid Build Coastguard Worker   // the mask of that's all ones on [msb, lsb].  Finally we not it to
1300*9880d681SAndroid Build Coastguard Worker   // create the final mask.
1301*9880d681SAndroid Build Coastguard Worker   unsigned msb = fieldFromInstruction(Val, 5, 5);
1302*9880d681SAndroid Build Coastguard Worker   unsigned lsb = fieldFromInstruction(Val, 0, 5);
1303*9880d681SAndroid Build Coastguard Worker 
1304*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1305*9880d681SAndroid Build Coastguard Worker   if (lsb > msb) {
1306*9880d681SAndroid Build Coastguard Worker     Check(S, MCDisassembler::SoftFail);
1307*9880d681SAndroid Build Coastguard Worker     // The check above will cause the warning for the "potentially undefined
1308*9880d681SAndroid Build Coastguard Worker     // instruction encoding" but we can't build a bad MCOperand value here
1309*9880d681SAndroid Build Coastguard Worker     // with a lsb > msb or else printing the MCInst will cause a crash.
1310*9880d681SAndroid Build Coastguard Worker     lsb = msb;
1311*9880d681SAndroid Build Coastguard Worker   }
1312*9880d681SAndroid Build Coastguard Worker 
1313*9880d681SAndroid Build Coastguard Worker   uint32_t msb_mask = 0xFFFFFFFF;
1314*9880d681SAndroid Build Coastguard Worker   if (msb != 31) msb_mask = (1U << (msb+1)) - 1;
1315*9880d681SAndroid Build Coastguard Worker   uint32_t lsb_mask = (1U << lsb) - 1;
1316*9880d681SAndroid Build Coastguard Worker 
1317*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(~(msb_mask ^ lsb_mask)));
1318*9880d681SAndroid Build Coastguard Worker   return S;
1319*9880d681SAndroid Build Coastguard Worker }
1320*9880d681SAndroid Build Coastguard Worker 
DecodeCopMemInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)1321*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn,
1322*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
1323*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1324*9880d681SAndroid Build Coastguard Worker 
1325*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
1326*9880d681SAndroid Build Coastguard Worker   unsigned CRd = fieldFromInstruction(Insn, 12, 4);
1327*9880d681SAndroid Build Coastguard Worker   unsigned coproc = fieldFromInstruction(Insn, 8, 4);
1328*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 8);
1329*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
1330*9880d681SAndroid Build Coastguard Worker   unsigned U = fieldFromInstruction(Insn, 23, 1);
1331*9880d681SAndroid Build Coastguard Worker 
1332*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
1333*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_OFFSET:
1334*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_PRE:
1335*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_POST:
1336*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_OPTION:
1337*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_OFFSET:
1338*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_PRE:
1339*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_POST:
1340*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_OPTION:
1341*9880d681SAndroid Build Coastguard Worker     case ARM::STC_OFFSET:
1342*9880d681SAndroid Build Coastguard Worker     case ARM::STC_PRE:
1343*9880d681SAndroid Build Coastguard Worker     case ARM::STC_POST:
1344*9880d681SAndroid Build Coastguard Worker     case ARM::STC_OPTION:
1345*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_OFFSET:
1346*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_PRE:
1347*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_POST:
1348*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_OPTION:
1349*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC_OFFSET:
1350*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC_PRE:
1351*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC_POST:
1352*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC_OPTION:
1353*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDCL_OFFSET:
1354*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDCL_PRE:
1355*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDCL_POST:
1356*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDCL_OPTION:
1357*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC_OFFSET:
1358*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC_PRE:
1359*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC_POST:
1360*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC_OPTION:
1361*9880d681SAndroid Build Coastguard Worker     case ARM::t2STCL_OFFSET:
1362*9880d681SAndroid Build Coastguard Worker     case ARM::t2STCL_PRE:
1363*9880d681SAndroid Build Coastguard Worker     case ARM::t2STCL_POST:
1364*9880d681SAndroid Build Coastguard Worker     case ARM::t2STCL_OPTION:
1365*9880d681SAndroid Build Coastguard Worker       if (coproc == 0xA || coproc == 0xB)
1366*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1367*9880d681SAndroid Build Coastguard Worker       break;
1368*9880d681SAndroid Build Coastguard Worker     default:
1369*9880d681SAndroid Build Coastguard Worker       break;
1370*9880d681SAndroid Build Coastguard Worker   }
1371*9880d681SAndroid Build Coastguard Worker 
1372*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
1373*9880d681SAndroid Build Coastguard Worker     ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
1374*9880d681SAndroid Build Coastguard Worker   if (featureBits[ARM::HasV8Ops] && (coproc != 14))
1375*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1376*9880d681SAndroid Build Coastguard Worker 
1377*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(coproc));
1378*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(CRd));
1379*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1380*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1381*9880d681SAndroid Build Coastguard Worker 
1382*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
1383*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC2_OFFSET:
1384*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC2L_OFFSET:
1385*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC2_PRE:
1386*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC2L_PRE:
1387*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC2_OFFSET:
1388*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC2L_OFFSET:
1389*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC2_PRE:
1390*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC2L_PRE:
1391*9880d681SAndroid Build Coastguard Worker     case ARM::LDC2_OFFSET:
1392*9880d681SAndroid Build Coastguard Worker     case ARM::LDC2L_OFFSET:
1393*9880d681SAndroid Build Coastguard Worker     case ARM::LDC2_PRE:
1394*9880d681SAndroid Build Coastguard Worker     case ARM::LDC2L_PRE:
1395*9880d681SAndroid Build Coastguard Worker     case ARM::STC2_OFFSET:
1396*9880d681SAndroid Build Coastguard Worker     case ARM::STC2L_OFFSET:
1397*9880d681SAndroid Build Coastguard Worker     case ARM::STC2_PRE:
1398*9880d681SAndroid Build Coastguard Worker     case ARM::STC2L_PRE:
1399*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC_OFFSET:
1400*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDCL_OFFSET:
1401*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC_PRE:
1402*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDCL_PRE:
1403*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC_OFFSET:
1404*9880d681SAndroid Build Coastguard Worker     case ARM::t2STCL_OFFSET:
1405*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC_PRE:
1406*9880d681SAndroid Build Coastguard Worker     case ARM::t2STCL_PRE:
1407*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_OFFSET:
1408*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_OFFSET:
1409*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_PRE:
1410*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_PRE:
1411*9880d681SAndroid Build Coastguard Worker     case ARM::STC_OFFSET:
1412*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_OFFSET:
1413*9880d681SAndroid Build Coastguard Worker     case ARM::STC_PRE:
1414*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_PRE:
1415*9880d681SAndroid Build Coastguard Worker       imm = ARM_AM::getAM5Opc(U ? ARM_AM::add : ARM_AM::sub, imm);
1416*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(imm));
1417*9880d681SAndroid Build Coastguard Worker       break;
1418*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC2_POST:
1419*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC2L_POST:
1420*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC2_POST:
1421*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC2L_POST:
1422*9880d681SAndroid Build Coastguard Worker     case ARM::LDC2_POST:
1423*9880d681SAndroid Build Coastguard Worker     case ARM::LDC2L_POST:
1424*9880d681SAndroid Build Coastguard Worker     case ARM::STC2_POST:
1425*9880d681SAndroid Build Coastguard Worker     case ARM::STC2L_POST:
1426*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDC_POST:
1427*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDCL_POST:
1428*9880d681SAndroid Build Coastguard Worker     case ARM::t2STC_POST:
1429*9880d681SAndroid Build Coastguard Worker     case ARM::t2STCL_POST:
1430*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_POST:
1431*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_POST:
1432*9880d681SAndroid Build Coastguard Worker     case ARM::STC_POST:
1433*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_POST:
1434*9880d681SAndroid Build Coastguard Worker       imm |= U << 8;
1435*9880d681SAndroid Build Coastguard Worker       // fall through.
1436*9880d681SAndroid Build Coastguard Worker     default:
1437*9880d681SAndroid Build Coastguard Worker       // The 'option' variant doesn't encode 'U' in the immediate since
1438*9880d681SAndroid Build Coastguard Worker       // the immediate is unsigned [0,255].
1439*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(imm));
1440*9880d681SAndroid Build Coastguard Worker       break;
1441*9880d681SAndroid Build Coastguard Worker   }
1442*9880d681SAndroid Build Coastguard Worker 
1443*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
1444*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_OFFSET:
1445*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_PRE:
1446*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_POST:
1447*9880d681SAndroid Build Coastguard Worker     case ARM::LDC_OPTION:
1448*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_OFFSET:
1449*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_PRE:
1450*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_POST:
1451*9880d681SAndroid Build Coastguard Worker     case ARM::LDCL_OPTION:
1452*9880d681SAndroid Build Coastguard Worker     case ARM::STC_OFFSET:
1453*9880d681SAndroid Build Coastguard Worker     case ARM::STC_PRE:
1454*9880d681SAndroid Build Coastguard Worker     case ARM::STC_POST:
1455*9880d681SAndroid Build Coastguard Worker     case ARM::STC_OPTION:
1456*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_OFFSET:
1457*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_PRE:
1458*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_POST:
1459*9880d681SAndroid Build Coastguard Worker     case ARM::STCL_OPTION:
1460*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
1461*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1462*9880d681SAndroid Build Coastguard Worker       break;
1463*9880d681SAndroid Build Coastguard Worker     default:
1464*9880d681SAndroid Build Coastguard Worker       break;
1465*9880d681SAndroid Build Coastguard Worker   }
1466*9880d681SAndroid Build Coastguard Worker 
1467*9880d681SAndroid Build Coastguard Worker   return S;
1468*9880d681SAndroid Build Coastguard Worker }
1469*9880d681SAndroid Build Coastguard Worker 
1470*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeAddrMode2IdxInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)1471*9880d681SAndroid Build Coastguard Worker DecodeAddrMode2IdxInstruction(MCInst &Inst, unsigned Insn,
1472*9880d681SAndroid Build Coastguard Worker                               uint64_t Address, const void *Decoder) {
1473*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1474*9880d681SAndroid Build Coastguard Worker 
1475*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
1476*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
1477*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
1478*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 12);
1479*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
1480*9880d681SAndroid Build Coastguard Worker   unsigned reg = fieldFromInstruction(Insn, 25, 1);
1481*9880d681SAndroid Build Coastguard Worker   unsigned P = fieldFromInstruction(Insn, 24, 1);
1482*9880d681SAndroid Build Coastguard Worker   unsigned W = fieldFromInstruction(Insn, 21, 1);
1483*9880d681SAndroid Build Coastguard Worker 
1484*9880d681SAndroid Build Coastguard Worker   // On stores, the writeback operand precedes Rt.
1485*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
1486*9880d681SAndroid Build Coastguard Worker     case ARM::STR_POST_IMM:
1487*9880d681SAndroid Build Coastguard Worker     case ARM::STR_POST_REG:
1488*9880d681SAndroid Build Coastguard Worker     case ARM::STRB_POST_IMM:
1489*9880d681SAndroid Build Coastguard Worker     case ARM::STRB_POST_REG:
1490*9880d681SAndroid Build Coastguard Worker     case ARM::STRT_POST_REG:
1491*9880d681SAndroid Build Coastguard Worker     case ARM::STRT_POST_IMM:
1492*9880d681SAndroid Build Coastguard Worker     case ARM::STRBT_POST_REG:
1493*9880d681SAndroid Build Coastguard Worker     case ARM::STRBT_POST_IMM:
1494*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1495*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1496*9880d681SAndroid Build Coastguard Worker       break;
1497*9880d681SAndroid Build Coastguard Worker     default:
1498*9880d681SAndroid Build Coastguard Worker       break;
1499*9880d681SAndroid Build Coastguard Worker   }
1500*9880d681SAndroid Build Coastguard Worker 
1501*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
1502*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1503*9880d681SAndroid Build Coastguard Worker 
1504*9880d681SAndroid Build Coastguard Worker   // On loads, the writeback operand comes after Rt.
1505*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
1506*9880d681SAndroid Build Coastguard Worker     case ARM::LDR_POST_IMM:
1507*9880d681SAndroid Build Coastguard Worker     case ARM::LDR_POST_REG:
1508*9880d681SAndroid Build Coastguard Worker     case ARM::LDRB_POST_IMM:
1509*9880d681SAndroid Build Coastguard Worker     case ARM::LDRB_POST_REG:
1510*9880d681SAndroid Build Coastguard Worker     case ARM::LDRBT_POST_REG:
1511*9880d681SAndroid Build Coastguard Worker     case ARM::LDRBT_POST_IMM:
1512*9880d681SAndroid Build Coastguard Worker     case ARM::LDRT_POST_REG:
1513*9880d681SAndroid Build Coastguard Worker     case ARM::LDRT_POST_IMM:
1514*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1515*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1516*9880d681SAndroid Build Coastguard Worker       break;
1517*9880d681SAndroid Build Coastguard Worker     default:
1518*9880d681SAndroid Build Coastguard Worker       break;
1519*9880d681SAndroid Build Coastguard Worker   }
1520*9880d681SAndroid Build Coastguard Worker 
1521*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1522*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1523*9880d681SAndroid Build Coastguard Worker 
1524*9880d681SAndroid Build Coastguard Worker   ARM_AM::AddrOpc Op = ARM_AM::add;
1525*9880d681SAndroid Build Coastguard Worker   if (!fieldFromInstruction(Insn, 23, 1))
1526*9880d681SAndroid Build Coastguard Worker     Op = ARM_AM::sub;
1527*9880d681SAndroid Build Coastguard Worker 
1528*9880d681SAndroid Build Coastguard Worker   bool writeback = (P == 0) || (W == 1);
1529*9880d681SAndroid Build Coastguard Worker   unsigned idx_mode = 0;
1530*9880d681SAndroid Build Coastguard Worker   if (P && writeback)
1531*9880d681SAndroid Build Coastguard Worker     idx_mode = ARMII::IndexModePre;
1532*9880d681SAndroid Build Coastguard Worker   else if (!P && writeback)
1533*9880d681SAndroid Build Coastguard Worker     idx_mode = ARMII::IndexModePost;
1534*9880d681SAndroid Build Coastguard Worker 
1535*9880d681SAndroid Build Coastguard Worker   if (writeback && (Rn == 15 || Rn == Rt))
1536*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail; // UNPREDICTABLE
1537*9880d681SAndroid Build Coastguard Worker 
1538*9880d681SAndroid Build Coastguard Worker   if (reg) {
1539*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)))
1540*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
1541*9880d681SAndroid Build Coastguard Worker     ARM_AM::ShiftOpc Opc = ARM_AM::lsl;
1542*9880d681SAndroid Build Coastguard Worker     switch( fieldFromInstruction(Insn, 5, 2)) {
1543*9880d681SAndroid Build Coastguard Worker       case 0:
1544*9880d681SAndroid Build Coastguard Worker         Opc = ARM_AM::lsl;
1545*9880d681SAndroid Build Coastguard Worker         break;
1546*9880d681SAndroid Build Coastguard Worker       case 1:
1547*9880d681SAndroid Build Coastguard Worker         Opc = ARM_AM::lsr;
1548*9880d681SAndroid Build Coastguard Worker         break;
1549*9880d681SAndroid Build Coastguard Worker       case 2:
1550*9880d681SAndroid Build Coastguard Worker         Opc = ARM_AM::asr;
1551*9880d681SAndroid Build Coastguard Worker         break;
1552*9880d681SAndroid Build Coastguard Worker       case 3:
1553*9880d681SAndroid Build Coastguard Worker         Opc = ARM_AM::ror;
1554*9880d681SAndroid Build Coastguard Worker         break;
1555*9880d681SAndroid Build Coastguard Worker       default:
1556*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1557*9880d681SAndroid Build Coastguard Worker     }
1558*9880d681SAndroid Build Coastguard Worker     unsigned amt = fieldFromInstruction(Insn, 7, 5);
1559*9880d681SAndroid Build Coastguard Worker     if (Opc == ARM_AM::ror && amt == 0)
1560*9880d681SAndroid Build Coastguard Worker       Opc = ARM_AM::rrx;
1561*9880d681SAndroid Build Coastguard Worker     unsigned imm = ARM_AM::getAM2Opc(Op, amt, Opc, idx_mode);
1562*9880d681SAndroid Build Coastguard Worker 
1563*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imm));
1564*9880d681SAndroid Build Coastguard Worker   } else {
1565*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(0));
1566*9880d681SAndroid Build Coastguard Worker     unsigned tmp = ARM_AM::getAM2Opc(Op, imm, ARM_AM::lsl, idx_mode);
1567*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(tmp));
1568*9880d681SAndroid Build Coastguard Worker   }
1569*9880d681SAndroid Build Coastguard Worker 
1570*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
1571*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1572*9880d681SAndroid Build Coastguard Worker 
1573*9880d681SAndroid Build Coastguard Worker   return S;
1574*9880d681SAndroid Build Coastguard Worker }
1575*9880d681SAndroid Build Coastguard Worker 
DecodeSORegMemOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)1576*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSORegMemOperand(MCInst &Inst, unsigned Val,
1577*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
1578*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1579*9880d681SAndroid Build Coastguard Worker 
1580*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 13, 4);
1581*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Val,  0, 4);
1582*9880d681SAndroid Build Coastguard Worker   unsigned type = fieldFromInstruction(Val, 5, 2);
1583*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 7, 5);
1584*9880d681SAndroid Build Coastguard Worker   unsigned U = fieldFromInstruction(Val, 12, 1);
1585*9880d681SAndroid Build Coastguard Worker 
1586*9880d681SAndroid Build Coastguard Worker   ARM_AM::ShiftOpc ShOp = ARM_AM::lsl;
1587*9880d681SAndroid Build Coastguard Worker   switch (type) {
1588*9880d681SAndroid Build Coastguard Worker     case 0:
1589*9880d681SAndroid Build Coastguard Worker       ShOp = ARM_AM::lsl;
1590*9880d681SAndroid Build Coastguard Worker       break;
1591*9880d681SAndroid Build Coastguard Worker     case 1:
1592*9880d681SAndroid Build Coastguard Worker       ShOp = ARM_AM::lsr;
1593*9880d681SAndroid Build Coastguard Worker       break;
1594*9880d681SAndroid Build Coastguard Worker     case 2:
1595*9880d681SAndroid Build Coastguard Worker       ShOp = ARM_AM::asr;
1596*9880d681SAndroid Build Coastguard Worker       break;
1597*9880d681SAndroid Build Coastguard Worker     case 3:
1598*9880d681SAndroid Build Coastguard Worker       ShOp = ARM_AM::ror;
1599*9880d681SAndroid Build Coastguard Worker       break;
1600*9880d681SAndroid Build Coastguard Worker   }
1601*9880d681SAndroid Build Coastguard Worker 
1602*9880d681SAndroid Build Coastguard Worker   if (ShOp == ARM_AM::ror && imm == 0)
1603*9880d681SAndroid Build Coastguard Worker     ShOp = ARM_AM::rrx;
1604*9880d681SAndroid Build Coastguard Worker 
1605*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1606*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1607*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
1608*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1609*9880d681SAndroid Build Coastguard Worker   unsigned shift;
1610*9880d681SAndroid Build Coastguard Worker   if (U)
1611*9880d681SAndroid Build Coastguard Worker     shift = ARM_AM::getAM2Opc(ARM_AM::add, imm, ShOp);
1612*9880d681SAndroid Build Coastguard Worker   else
1613*9880d681SAndroid Build Coastguard Worker     shift = ARM_AM::getAM2Opc(ARM_AM::sub, imm, ShOp);
1614*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(shift));
1615*9880d681SAndroid Build Coastguard Worker 
1616*9880d681SAndroid Build Coastguard Worker   return S;
1617*9880d681SAndroid Build Coastguard Worker }
1618*9880d681SAndroid Build Coastguard Worker 
1619*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeAddrMode3Instruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)1620*9880d681SAndroid Build Coastguard Worker DecodeAddrMode3Instruction(MCInst &Inst, unsigned Insn,
1621*9880d681SAndroid Build Coastguard Worker                            uint64_t Address, const void *Decoder) {
1622*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1623*9880d681SAndroid Build Coastguard Worker 
1624*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
1625*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
1626*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
1627*9880d681SAndroid Build Coastguard Worker   unsigned type = fieldFromInstruction(Insn, 22, 1);
1628*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 8, 4);
1629*9880d681SAndroid Build Coastguard Worker   unsigned U = ((~fieldFromInstruction(Insn, 23, 1)) & 1) << 8;
1630*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
1631*9880d681SAndroid Build Coastguard Worker   unsigned W = fieldFromInstruction(Insn, 21, 1);
1632*9880d681SAndroid Build Coastguard Worker   unsigned P = fieldFromInstruction(Insn, 24, 1);
1633*9880d681SAndroid Build Coastguard Worker   unsigned Rt2 = Rt + 1;
1634*9880d681SAndroid Build Coastguard Worker 
1635*9880d681SAndroid Build Coastguard Worker   bool writeback = (W == 1) | (P == 0);
1636*9880d681SAndroid Build Coastguard Worker 
1637*9880d681SAndroid Build Coastguard Worker   // For {LD,ST}RD, Rt must be even, else undefined.
1638*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
1639*9880d681SAndroid Build Coastguard Worker     case ARM::STRD:
1640*9880d681SAndroid Build Coastguard Worker     case ARM::STRD_PRE:
1641*9880d681SAndroid Build Coastguard Worker     case ARM::STRD_POST:
1642*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD:
1643*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD_PRE:
1644*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD_POST:
1645*9880d681SAndroid Build Coastguard Worker       if (Rt & 0x1) S = MCDisassembler::SoftFail;
1646*9880d681SAndroid Build Coastguard Worker       break;
1647*9880d681SAndroid Build Coastguard Worker     default:
1648*9880d681SAndroid Build Coastguard Worker       break;
1649*9880d681SAndroid Build Coastguard Worker   }
1650*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
1651*9880d681SAndroid Build Coastguard Worker     case ARM::STRD:
1652*9880d681SAndroid Build Coastguard Worker     case ARM::STRD_PRE:
1653*9880d681SAndroid Build Coastguard Worker     case ARM::STRD_POST:
1654*9880d681SAndroid Build Coastguard Worker       if (P == 0 && W == 1)
1655*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1656*9880d681SAndroid Build Coastguard Worker 
1657*9880d681SAndroid Build Coastguard Worker       if (writeback && (Rn == 15 || Rn == Rt || Rn == Rt2))
1658*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1659*9880d681SAndroid Build Coastguard Worker       if (type && Rm == 15)
1660*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1661*9880d681SAndroid Build Coastguard Worker       if (Rt2 == 15)
1662*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1663*9880d681SAndroid Build Coastguard Worker       if (!type && fieldFromInstruction(Insn, 8, 4))
1664*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1665*9880d681SAndroid Build Coastguard Worker       break;
1666*9880d681SAndroid Build Coastguard Worker     case ARM::STRH:
1667*9880d681SAndroid Build Coastguard Worker     case ARM::STRH_PRE:
1668*9880d681SAndroid Build Coastguard Worker     case ARM::STRH_POST:
1669*9880d681SAndroid Build Coastguard Worker       if (Rt == 15)
1670*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1671*9880d681SAndroid Build Coastguard Worker       if (writeback && (Rn == 15 || Rn == Rt))
1672*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1673*9880d681SAndroid Build Coastguard Worker       if (!type && Rm == 15)
1674*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1675*9880d681SAndroid Build Coastguard Worker       break;
1676*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD:
1677*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD_PRE:
1678*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD_POST:
1679*9880d681SAndroid Build Coastguard Worker       if (type && Rn == 15){
1680*9880d681SAndroid Build Coastguard Worker         if (Rt2 == 15)
1681*9880d681SAndroid Build Coastguard Worker           S = MCDisassembler::SoftFail;
1682*9880d681SAndroid Build Coastguard Worker         break;
1683*9880d681SAndroid Build Coastguard Worker       }
1684*9880d681SAndroid Build Coastguard Worker       if (P == 0 && W == 1)
1685*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1686*9880d681SAndroid Build Coastguard Worker       if (!type && (Rt2 == 15 || Rm == 15 || Rm == Rt || Rm == Rt2))
1687*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1688*9880d681SAndroid Build Coastguard Worker       if (!type && writeback && Rn == 15)
1689*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1690*9880d681SAndroid Build Coastguard Worker       if (writeback && (Rn == Rt || Rn == Rt2))
1691*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1692*9880d681SAndroid Build Coastguard Worker       break;
1693*9880d681SAndroid Build Coastguard Worker     case ARM::LDRH:
1694*9880d681SAndroid Build Coastguard Worker     case ARM::LDRH_PRE:
1695*9880d681SAndroid Build Coastguard Worker     case ARM::LDRH_POST:
1696*9880d681SAndroid Build Coastguard Worker       if (type && Rn == 15){
1697*9880d681SAndroid Build Coastguard Worker         if (Rt == 15)
1698*9880d681SAndroid Build Coastguard Worker           S = MCDisassembler::SoftFail;
1699*9880d681SAndroid Build Coastguard Worker         break;
1700*9880d681SAndroid Build Coastguard Worker       }
1701*9880d681SAndroid Build Coastguard Worker       if (Rt == 15)
1702*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1703*9880d681SAndroid Build Coastguard Worker       if (!type && Rm == 15)
1704*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1705*9880d681SAndroid Build Coastguard Worker       if (!type && writeback && (Rn == 15 || Rn == Rt))
1706*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1707*9880d681SAndroid Build Coastguard Worker       break;
1708*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSH:
1709*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSH_PRE:
1710*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSH_POST:
1711*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSB:
1712*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSB_PRE:
1713*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSB_POST:
1714*9880d681SAndroid Build Coastguard Worker       if (type && Rn == 15){
1715*9880d681SAndroid Build Coastguard Worker         if (Rt == 15)
1716*9880d681SAndroid Build Coastguard Worker           S = MCDisassembler::SoftFail;
1717*9880d681SAndroid Build Coastguard Worker         break;
1718*9880d681SAndroid Build Coastguard Worker       }
1719*9880d681SAndroid Build Coastguard Worker       if (type && (Rt == 15 || (writeback && Rn == Rt)))
1720*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1721*9880d681SAndroid Build Coastguard Worker       if (!type && (Rt == 15 || Rm == 15))
1722*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1723*9880d681SAndroid Build Coastguard Worker       if (!type && writeback && (Rn == 15 || Rn == Rt))
1724*9880d681SAndroid Build Coastguard Worker         S = MCDisassembler::SoftFail;
1725*9880d681SAndroid Build Coastguard Worker       break;
1726*9880d681SAndroid Build Coastguard Worker     default:
1727*9880d681SAndroid Build Coastguard Worker       break;
1728*9880d681SAndroid Build Coastguard Worker   }
1729*9880d681SAndroid Build Coastguard Worker 
1730*9880d681SAndroid Build Coastguard Worker   if (writeback) { // Writeback
1731*9880d681SAndroid Build Coastguard Worker     if (P)
1732*9880d681SAndroid Build Coastguard Worker       U |= ARMII::IndexModePre << 9;
1733*9880d681SAndroid Build Coastguard Worker     else
1734*9880d681SAndroid Build Coastguard Worker       U |= ARMII::IndexModePost << 9;
1735*9880d681SAndroid Build Coastguard Worker 
1736*9880d681SAndroid Build Coastguard Worker     // On stores, the writeback operand precedes Rt.
1737*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
1738*9880d681SAndroid Build Coastguard Worker     case ARM::STRD:
1739*9880d681SAndroid Build Coastguard Worker     case ARM::STRD_PRE:
1740*9880d681SAndroid Build Coastguard Worker     case ARM::STRD_POST:
1741*9880d681SAndroid Build Coastguard Worker     case ARM::STRH:
1742*9880d681SAndroid Build Coastguard Worker     case ARM::STRH_PRE:
1743*9880d681SAndroid Build Coastguard Worker     case ARM::STRH_POST:
1744*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1745*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1746*9880d681SAndroid Build Coastguard Worker       break;
1747*9880d681SAndroid Build Coastguard Worker     default:
1748*9880d681SAndroid Build Coastguard Worker       break;
1749*9880d681SAndroid Build Coastguard Worker     }
1750*9880d681SAndroid Build Coastguard Worker   }
1751*9880d681SAndroid Build Coastguard Worker 
1752*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
1753*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1754*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
1755*9880d681SAndroid Build Coastguard Worker     case ARM::STRD:
1756*9880d681SAndroid Build Coastguard Worker     case ARM::STRD_PRE:
1757*9880d681SAndroid Build Coastguard Worker     case ARM::STRD_POST:
1758*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD:
1759*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD_PRE:
1760*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD_POST:
1761*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder)))
1762*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1763*9880d681SAndroid Build Coastguard Worker       break;
1764*9880d681SAndroid Build Coastguard Worker     default:
1765*9880d681SAndroid Build Coastguard Worker       break;
1766*9880d681SAndroid Build Coastguard Worker   }
1767*9880d681SAndroid Build Coastguard Worker 
1768*9880d681SAndroid Build Coastguard Worker   if (writeback) {
1769*9880d681SAndroid Build Coastguard Worker     // On loads, the writeback operand comes after Rt.
1770*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
1771*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD:
1772*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD_PRE:
1773*9880d681SAndroid Build Coastguard Worker     case ARM::LDRD_POST:
1774*9880d681SAndroid Build Coastguard Worker     case ARM::LDRH:
1775*9880d681SAndroid Build Coastguard Worker     case ARM::LDRH_PRE:
1776*9880d681SAndroid Build Coastguard Worker     case ARM::LDRH_POST:
1777*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSH:
1778*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSH_PRE:
1779*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSH_POST:
1780*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSB:
1781*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSB_PRE:
1782*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSB_POST:
1783*9880d681SAndroid Build Coastguard Worker     case ARM::LDRHTr:
1784*9880d681SAndroid Build Coastguard Worker     case ARM::LDRSBTr:
1785*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1786*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1787*9880d681SAndroid Build Coastguard Worker       break;
1788*9880d681SAndroid Build Coastguard Worker     default:
1789*9880d681SAndroid Build Coastguard Worker       break;
1790*9880d681SAndroid Build Coastguard Worker     }
1791*9880d681SAndroid Build Coastguard Worker   }
1792*9880d681SAndroid Build Coastguard Worker 
1793*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1794*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1795*9880d681SAndroid Build Coastguard Worker 
1796*9880d681SAndroid Build Coastguard Worker   if (type) {
1797*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(0));
1798*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(U | (imm << 4) | Rm));
1799*9880d681SAndroid Build Coastguard Worker   } else {
1800*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
1801*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1802*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(U));
1803*9880d681SAndroid Build Coastguard Worker   }
1804*9880d681SAndroid Build Coastguard Worker 
1805*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
1806*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1807*9880d681SAndroid Build Coastguard Worker 
1808*9880d681SAndroid Build Coastguard Worker   return S;
1809*9880d681SAndroid Build Coastguard Worker }
1810*9880d681SAndroid Build Coastguard Worker 
DecodeRFEInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)1811*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeRFEInstruction(MCInst &Inst, unsigned Insn,
1812*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
1813*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1814*9880d681SAndroid Build Coastguard Worker 
1815*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
1816*9880d681SAndroid Build Coastguard Worker   unsigned mode = fieldFromInstruction(Insn, 23, 2);
1817*9880d681SAndroid Build Coastguard Worker 
1818*9880d681SAndroid Build Coastguard Worker   switch (mode) {
1819*9880d681SAndroid Build Coastguard Worker     case 0:
1820*9880d681SAndroid Build Coastguard Worker       mode = ARM_AM::da;
1821*9880d681SAndroid Build Coastguard Worker       break;
1822*9880d681SAndroid Build Coastguard Worker     case 1:
1823*9880d681SAndroid Build Coastguard Worker       mode = ARM_AM::ia;
1824*9880d681SAndroid Build Coastguard Worker       break;
1825*9880d681SAndroid Build Coastguard Worker     case 2:
1826*9880d681SAndroid Build Coastguard Worker       mode = ARM_AM::db;
1827*9880d681SAndroid Build Coastguard Worker       break;
1828*9880d681SAndroid Build Coastguard Worker     case 3:
1829*9880d681SAndroid Build Coastguard Worker       mode = ARM_AM::ib;
1830*9880d681SAndroid Build Coastguard Worker       break;
1831*9880d681SAndroid Build Coastguard Worker   }
1832*9880d681SAndroid Build Coastguard Worker 
1833*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(mode));
1834*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1835*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1836*9880d681SAndroid Build Coastguard Worker 
1837*9880d681SAndroid Build Coastguard Worker   return S;
1838*9880d681SAndroid Build Coastguard Worker }
1839*9880d681SAndroid Build Coastguard Worker 
DecodeQADDInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)1840*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeQADDInstruction(MCInst &Inst, unsigned Insn,
1841*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
1842*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1843*9880d681SAndroid Build Coastguard Worker 
1844*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
1845*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
1846*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
1847*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
1848*9880d681SAndroid Build Coastguard Worker 
1849*9880d681SAndroid Build Coastguard Worker   if (pred == 0xF)
1850*9880d681SAndroid Build Coastguard Worker     return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
1851*9880d681SAndroid Build Coastguard Worker 
1852*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder)))
1853*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1854*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)))
1855*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1856*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
1857*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1858*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
1859*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1860*9880d681SAndroid Build Coastguard Worker   return S;
1861*9880d681SAndroid Build Coastguard Worker }
1862*9880d681SAndroid Build Coastguard Worker 
DecodeMemMultipleWritebackInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)1863*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeMemMultipleWritebackInstruction(MCInst &Inst,
1864*9880d681SAndroid Build Coastguard Worker                                   unsigned Insn,
1865*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
1866*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1867*9880d681SAndroid Build Coastguard Worker 
1868*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
1869*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
1870*9880d681SAndroid Build Coastguard Worker   unsigned reglist = fieldFromInstruction(Insn, 0, 16);
1871*9880d681SAndroid Build Coastguard Worker 
1872*9880d681SAndroid Build Coastguard Worker   if (pred == 0xF) {
1873*9880d681SAndroid Build Coastguard Worker     // Ambiguous with RFE and SRS
1874*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
1875*9880d681SAndroid Build Coastguard Worker       case ARM::LDMDA:
1876*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::RFEDA);
1877*9880d681SAndroid Build Coastguard Worker         break;
1878*9880d681SAndroid Build Coastguard Worker       case ARM::LDMDA_UPD:
1879*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::RFEDA_UPD);
1880*9880d681SAndroid Build Coastguard Worker         break;
1881*9880d681SAndroid Build Coastguard Worker       case ARM::LDMDB:
1882*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::RFEDB);
1883*9880d681SAndroid Build Coastguard Worker         break;
1884*9880d681SAndroid Build Coastguard Worker       case ARM::LDMDB_UPD:
1885*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::RFEDB_UPD);
1886*9880d681SAndroid Build Coastguard Worker         break;
1887*9880d681SAndroid Build Coastguard Worker       case ARM::LDMIA:
1888*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::RFEIA);
1889*9880d681SAndroid Build Coastguard Worker         break;
1890*9880d681SAndroid Build Coastguard Worker       case ARM::LDMIA_UPD:
1891*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::RFEIA_UPD);
1892*9880d681SAndroid Build Coastguard Worker         break;
1893*9880d681SAndroid Build Coastguard Worker       case ARM::LDMIB:
1894*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::RFEIB);
1895*9880d681SAndroid Build Coastguard Worker         break;
1896*9880d681SAndroid Build Coastguard Worker       case ARM::LDMIB_UPD:
1897*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::RFEIB_UPD);
1898*9880d681SAndroid Build Coastguard Worker         break;
1899*9880d681SAndroid Build Coastguard Worker       case ARM::STMDA:
1900*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::SRSDA);
1901*9880d681SAndroid Build Coastguard Worker         break;
1902*9880d681SAndroid Build Coastguard Worker       case ARM::STMDA_UPD:
1903*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::SRSDA_UPD);
1904*9880d681SAndroid Build Coastguard Worker         break;
1905*9880d681SAndroid Build Coastguard Worker       case ARM::STMDB:
1906*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::SRSDB);
1907*9880d681SAndroid Build Coastguard Worker         break;
1908*9880d681SAndroid Build Coastguard Worker       case ARM::STMDB_UPD:
1909*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::SRSDB_UPD);
1910*9880d681SAndroid Build Coastguard Worker         break;
1911*9880d681SAndroid Build Coastguard Worker       case ARM::STMIA:
1912*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::SRSIA);
1913*9880d681SAndroid Build Coastguard Worker         break;
1914*9880d681SAndroid Build Coastguard Worker       case ARM::STMIA_UPD:
1915*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::SRSIA_UPD);
1916*9880d681SAndroid Build Coastguard Worker         break;
1917*9880d681SAndroid Build Coastguard Worker       case ARM::STMIB:
1918*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::SRSIB);
1919*9880d681SAndroid Build Coastguard Worker         break;
1920*9880d681SAndroid Build Coastguard Worker       case ARM::STMIB_UPD:
1921*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::SRSIB_UPD);
1922*9880d681SAndroid Build Coastguard Worker         break;
1923*9880d681SAndroid Build Coastguard Worker       default:
1924*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1925*9880d681SAndroid Build Coastguard Worker     }
1926*9880d681SAndroid Build Coastguard Worker 
1927*9880d681SAndroid Build Coastguard Worker     // For stores (which become SRS's, the only operand is the mode.
1928*9880d681SAndroid Build Coastguard Worker     if (fieldFromInstruction(Insn, 20, 1) == 0) {
1929*9880d681SAndroid Build Coastguard Worker       // Check SRS encoding constraints
1930*9880d681SAndroid Build Coastguard Worker       if (!(fieldFromInstruction(Insn, 22, 1) == 1 &&
1931*9880d681SAndroid Build Coastguard Worker             fieldFromInstruction(Insn, 20, 1) == 0))
1932*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
1933*9880d681SAndroid Build Coastguard Worker 
1934*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(
1935*9880d681SAndroid Build Coastguard Worker           MCOperand::createImm(fieldFromInstruction(Insn, 0, 4)));
1936*9880d681SAndroid Build Coastguard Worker       return S;
1937*9880d681SAndroid Build Coastguard Worker     }
1938*9880d681SAndroid Build Coastguard Worker 
1939*9880d681SAndroid Build Coastguard Worker     return DecodeRFEInstruction(Inst, Insn, Address, Decoder);
1940*9880d681SAndroid Build Coastguard Worker   }
1941*9880d681SAndroid Build Coastguard Worker 
1942*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1943*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1944*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
1945*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail; // Tied
1946*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
1947*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1948*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeRegListOperand(Inst, reglist, Address, Decoder)))
1949*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1950*9880d681SAndroid Build Coastguard Worker 
1951*9880d681SAndroid Build Coastguard Worker   return S;
1952*9880d681SAndroid Build Coastguard Worker }
1953*9880d681SAndroid Build Coastguard Worker 
1954*9880d681SAndroid Build Coastguard Worker // Check for UNPREDICTABLE predicated ESB instruction
DecodeHINTInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)1955*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeHINTInstruction(MCInst &Inst, unsigned Insn,
1956*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
1957*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
1958*9880d681SAndroid Build Coastguard Worker   unsigned imm8 = fieldFromInstruction(Insn, 0, 8);
1959*9880d681SAndroid Build Coastguard Worker   const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
1960*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &FeatureBits = Dis->getSubtargetInfo().getFeatureBits();
1961*9880d681SAndroid Build Coastguard Worker 
1962*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1963*9880d681SAndroid Build Coastguard Worker 
1964*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm8));
1965*9880d681SAndroid Build Coastguard Worker 
1966*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
1967*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1968*9880d681SAndroid Build Coastguard Worker 
1969*9880d681SAndroid Build Coastguard Worker   // ESB is unpredictable if pred != AL. Without the RAS extension, it is a NOP,
1970*9880d681SAndroid Build Coastguard Worker   // so all predicates should be allowed.
1971*9880d681SAndroid Build Coastguard Worker   if (imm8 == 0x10 && pred != 0xe && ((FeatureBits[ARM::FeatureRAS]) != 0))
1972*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
1973*9880d681SAndroid Build Coastguard Worker 
1974*9880d681SAndroid Build Coastguard Worker   return S;
1975*9880d681SAndroid Build Coastguard Worker }
1976*9880d681SAndroid Build Coastguard Worker 
DecodeCPSInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)1977*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeCPSInstruction(MCInst &Inst, unsigned Insn,
1978*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
1979*9880d681SAndroid Build Coastguard Worker   unsigned imod = fieldFromInstruction(Insn, 18, 2);
1980*9880d681SAndroid Build Coastguard Worker   unsigned M = fieldFromInstruction(Insn, 17, 1);
1981*9880d681SAndroid Build Coastguard Worker   unsigned iflags = fieldFromInstruction(Insn, 6, 3);
1982*9880d681SAndroid Build Coastguard Worker   unsigned mode = fieldFromInstruction(Insn, 0, 5);
1983*9880d681SAndroid Build Coastguard Worker 
1984*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
1985*9880d681SAndroid Build Coastguard Worker 
1986*9880d681SAndroid Build Coastguard Worker   // This decoder is called from multiple location that do not check
1987*9880d681SAndroid Build Coastguard Worker   // the full encoding is valid before they do.
1988*9880d681SAndroid Build Coastguard Worker   if (fieldFromInstruction(Insn, 5, 1) != 0 ||
1989*9880d681SAndroid Build Coastguard Worker       fieldFromInstruction(Insn, 16, 1) != 0 ||
1990*9880d681SAndroid Build Coastguard Worker       fieldFromInstruction(Insn, 20, 8) != 0x10)
1991*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
1992*9880d681SAndroid Build Coastguard Worker 
1993*9880d681SAndroid Build Coastguard Worker   // imod == '01' --> UNPREDICTABLE
1994*9880d681SAndroid Build Coastguard Worker   // NOTE: Even though this is technically UNPREDICTABLE, we choose to
1995*9880d681SAndroid Build Coastguard Worker   // return failure here.  The '01' imod value is unprintable, so there's
1996*9880d681SAndroid Build Coastguard Worker   // nothing useful we could do even if we returned UNPREDICTABLE.
1997*9880d681SAndroid Build Coastguard Worker 
1998*9880d681SAndroid Build Coastguard Worker   if (imod == 1) return MCDisassembler::Fail;
1999*9880d681SAndroid Build Coastguard Worker 
2000*9880d681SAndroid Build Coastguard Worker   if (imod && M) {
2001*9880d681SAndroid Build Coastguard Worker     Inst.setOpcode(ARM::CPS3p);
2002*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imod));
2003*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(iflags));
2004*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(mode));
2005*9880d681SAndroid Build Coastguard Worker   } else if (imod && !M) {
2006*9880d681SAndroid Build Coastguard Worker     Inst.setOpcode(ARM::CPS2p);
2007*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imod));
2008*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(iflags));
2009*9880d681SAndroid Build Coastguard Worker     if (mode) S = MCDisassembler::SoftFail;
2010*9880d681SAndroid Build Coastguard Worker   } else if (!imod && M) {
2011*9880d681SAndroid Build Coastguard Worker     Inst.setOpcode(ARM::CPS1p);
2012*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(mode));
2013*9880d681SAndroid Build Coastguard Worker     if (iflags) S = MCDisassembler::SoftFail;
2014*9880d681SAndroid Build Coastguard Worker   } else {
2015*9880d681SAndroid Build Coastguard Worker     // imod == '00' && M == '0' --> UNPREDICTABLE
2016*9880d681SAndroid Build Coastguard Worker     Inst.setOpcode(ARM::CPS1p);
2017*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(mode));
2018*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
2019*9880d681SAndroid Build Coastguard Worker   }
2020*9880d681SAndroid Build Coastguard Worker 
2021*9880d681SAndroid Build Coastguard Worker   return S;
2022*9880d681SAndroid Build Coastguard Worker }
2023*9880d681SAndroid Build Coastguard Worker 
DecodeT2CPSInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2024*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2CPSInstruction(MCInst &Inst, unsigned Insn,
2025*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
2026*9880d681SAndroid Build Coastguard Worker   unsigned imod = fieldFromInstruction(Insn, 9, 2);
2027*9880d681SAndroid Build Coastguard Worker   unsigned M = fieldFromInstruction(Insn, 8, 1);
2028*9880d681SAndroid Build Coastguard Worker   unsigned iflags = fieldFromInstruction(Insn, 5, 3);
2029*9880d681SAndroid Build Coastguard Worker   unsigned mode = fieldFromInstruction(Insn, 0, 5);
2030*9880d681SAndroid Build Coastguard Worker 
2031*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2032*9880d681SAndroid Build Coastguard Worker 
2033*9880d681SAndroid Build Coastguard Worker   // imod == '01' --> UNPREDICTABLE
2034*9880d681SAndroid Build Coastguard Worker   // NOTE: Even though this is technically UNPREDICTABLE, we choose to
2035*9880d681SAndroid Build Coastguard Worker   // return failure here.  The '01' imod value is unprintable, so there's
2036*9880d681SAndroid Build Coastguard Worker   // nothing useful we could do even if we returned UNPREDICTABLE.
2037*9880d681SAndroid Build Coastguard Worker 
2038*9880d681SAndroid Build Coastguard Worker   if (imod == 1) return MCDisassembler::Fail;
2039*9880d681SAndroid Build Coastguard Worker 
2040*9880d681SAndroid Build Coastguard Worker   if (imod && M) {
2041*9880d681SAndroid Build Coastguard Worker     Inst.setOpcode(ARM::t2CPS3p);
2042*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imod));
2043*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(iflags));
2044*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(mode));
2045*9880d681SAndroid Build Coastguard Worker   } else if (imod && !M) {
2046*9880d681SAndroid Build Coastguard Worker     Inst.setOpcode(ARM::t2CPS2p);
2047*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imod));
2048*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(iflags));
2049*9880d681SAndroid Build Coastguard Worker     if (mode) S = MCDisassembler::SoftFail;
2050*9880d681SAndroid Build Coastguard Worker   } else if (!imod && M) {
2051*9880d681SAndroid Build Coastguard Worker     Inst.setOpcode(ARM::t2CPS1p);
2052*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(mode));
2053*9880d681SAndroid Build Coastguard Worker     if (iflags) S = MCDisassembler::SoftFail;
2054*9880d681SAndroid Build Coastguard Worker   } else {
2055*9880d681SAndroid Build Coastguard Worker     // imod == '00' && M == '0' --> this is a HINT instruction
2056*9880d681SAndroid Build Coastguard Worker     int imm = fieldFromInstruction(Insn, 0, 8);
2057*9880d681SAndroid Build Coastguard Worker     // HINT are defined only for immediate in [0..4]
2058*9880d681SAndroid Build Coastguard Worker     if(imm > 4) return MCDisassembler::Fail;
2059*9880d681SAndroid Build Coastguard Worker     Inst.setOpcode(ARM::t2HINT);
2060*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imm));
2061*9880d681SAndroid Build Coastguard Worker   }
2062*9880d681SAndroid Build Coastguard Worker 
2063*9880d681SAndroid Build Coastguard Worker   return S;
2064*9880d681SAndroid Build Coastguard Worker }
2065*9880d681SAndroid Build Coastguard Worker 
DecodeT2MOVTWInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2066*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2MOVTWInstruction(MCInst &Inst, unsigned Insn,
2067*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
2068*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2069*9880d681SAndroid Build Coastguard Worker 
2070*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 8, 4);
2071*9880d681SAndroid Build Coastguard Worker   unsigned imm = 0;
2072*9880d681SAndroid Build Coastguard Worker 
2073*9880d681SAndroid Build Coastguard Worker   imm |= (fieldFromInstruction(Insn, 0, 8) << 0);
2074*9880d681SAndroid Build Coastguard Worker   imm |= (fieldFromInstruction(Insn, 12, 3) << 8);
2075*9880d681SAndroid Build Coastguard Worker   imm |= (fieldFromInstruction(Insn, 16, 4) << 12);
2076*9880d681SAndroid Build Coastguard Worker   imm |= (fieldFromInstruction(Insn, 26, 1) << 11);
2077*9880d681SAndroid Build Coastguard Worker 
2078*9880d681SAndroid Build Coastguard Worker   if (Inst.getOpcode() == ARM::t2MOVTi16)
2079*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
2080*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2081*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
2082*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2083*9880d681SAndroid Build Coastguard Worker 
2084*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address, imm, false, 4, Inst, Decoder))
2085*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imm));
2086*9880d681SAndroid Build Coastguard Worker 
2087*9880d681SAndroid Build Coastguard Worker   return S;
2088*9880d681SAndroid Build Coastguard Worker }
2089*9880d681SAndroid Build Coastguard Worker 
DecodeArmMOVTWInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2090*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeArmMOVTWInstruction(MCInst &Inst, unsigned Insn,
2091*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
2092*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2093*9880d681SAndroid Build Coastguard Worker 
2094*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
2095*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
2096*9880d681SAndroid Build Coastguard Worker   unsigned imm = 0;
2097*9880d681SAndroid Build Coastguard Worker 
2098*9880d681SAndroid Build Coastguard Worker   imm |= (fieldFromInstruction(Insn, 0, 12) << 0);
2099*9880d681SAndroid Build Coastguard Worker   imm |= (fieldFromInstruction(Insn, 16, 4) << 12);
2100*9880d681SAndroid Build Coastguard Worker 
2101*9880d681SAndroid Build Coastguard Worker   if (Inst.getOpcode() == ARM::MOVTi16)
2102*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder)))
2103*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2104*9880d681SAndroid Build Coastguard Worker 
2105*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder)))
2106*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2107*9880d681SAndroid Build Coastguard Worker 
2108*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address, imm, false, 4, Inst, Decoder))
2109*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imm));
2110*9880d681SAndroid Build Coastguard Worker 
2111*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
2112*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2113*9880d681SAndroid Build Coastguard Worker 
2114*9880d681SAndroid Build Coastguard Worker   return S;
2115*9880d681SAndroid Build Coastguard Worker }
2116*9880d681SAndroid Build Coastguard Worker 
DecodeSMLAInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2117*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSMLAInstruction(MCInst &Inst, unsigned Insn,
2118*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
2119*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2120*9880d681SAndroid Build Coastguard Worker 
2121*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 16, 4);
2122*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 0, 4);
2123*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 8, 4);
2124*9880d681SAndroid Build Coastguard Worker   unsigned Ra = fieldFromInstruction(Insn, 12, 4);
2125*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
2126*9880d681SAndroid Build Coastguard Worker 
2127*9880d681SAndroid Build Coastguard Worker   if (pred == 0xF)
2128*9880d681SAndroid Build Coastguard Worker     return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
2129*9880d681SAndroid Build Coastguard Worker 
2130*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder)))
2131*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2132*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
2133*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2134*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)))
2135*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2136*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Ra, Address, Decoder)))
2137*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2138*9880d681SAndroid Build Coastguard Worker 
2139*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
2140*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2141*9880d681SAndroid Build Coastguard Worker 
2142*9880d681SAndroid Build Coastguard Worker   return S;
2143*9880d681SAndroid Build Coastguard Worker }
2144*9880d681SAndroid Build Coastguard Worker 
DecodeTSTInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2145*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeTSTInstruction(MCInst &Inst, unsigned Insn,
2146*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
2147*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2148*9880d681SAndroid Build Coastguard Worker 
2149*9880d681SAndroid Build Coastguard Worker   unsigned Pred = fieldFromInstruction(Insn, 28, 4);
2150*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
2151*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
2152*9880d681SAndroid Build Coastguard Worker 
2153*9880d681SAndroid Build Coastguard Worker   if (Pred == 0xF)
2154*9880d681SAndroid Build Coastguard Worker     return DecodeSETPANInstruction(Inst, Insn, Address, Decoder);
2155*9880d681SAndroid Build Coastguard Worker 
2156*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
2157*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2158*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
2159*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2160*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, Pred, Address, Decoder)))
2161*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2162*9880d681SAndroid Build Coastguard Worker 
2163*9880d681SAndroid Build Coastguard Worker   return S;
2164*9880d681SAndroid Build Coastguard Worker }
2165*9880d681SAndroid Build Coastguard Worker 
DecodeSETPANInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2166*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSETPANInstruction(MCInst &Inst, unsigned Insn,
2167*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
2168*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2169*9880d681SAndroid Build Coastguard Worker 
2170*9880d681SAndroid Build Coastguard Worker   unsigned Imm = fieldFromInstruction(Insn, 9, 1);
2171*9880d681SAndroid Build Coastguard Worker 
2172*9880d681SAndroid Build Coastguard Worker   const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
2173*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &FeatureBits = Dis->getSubtargetInfo().getFeatureBits();
2174*9880d681SAndroid Build Coastguard Worker 
2175*9880d681SAndroid Build Coastguard Worker   if (!FeatureBits[ARM::HasV8_1aOps] ||
2176*9880d681SAndroid Build Coastguard Worker       !FeatureBits[ARM::HasV8Ops])
2177*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2178*9880d681SAndroid Build Coastguard Worker 
2179*9880d681SAndroid Build Coastguard Worker   // Decoder can be called from DecodeTST, which does not check the full
2180*9880d681SAndroid Build Coastguard Worker   // encoding is valid.
2181*9880d681SAndroid Build Coastguard Worker   if (fieldFromInstruction(Insn, 20,12) != 0xf11 ||
2182*9880d681SAndroid Build Coastguard Worker       fieldFromInstruction(Insn, 4,4) != 0)
2183*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2184*9880d681SAndroid Build Coastguard Worker   if (fieldFromInstruction(Insn, 10,10) != 0 ||
2185*9880d681SAndroid Build Coastguard Worker       fieldFromInstruction(Insn, 0,4) != 0)
2186*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
2187*9880d681SAndroid Build Coastguard Worker 
2188*9880d681SAndroid Build Coastguard Worker   Inst.setOpcode(ARM::SETPAN);
2189*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Imm));
2190*9880d681SAndroid Build Coastguard Worker 
2191*9880d681SAndroid Build Coastguard Worker   return S;
2192*9880d681SAndroid Build Coastguard Worker }
2193*9880d681SAndroid Build Coastguard Worker 
DecodeAddrModeImm12Operand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)2194*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrModeImm12Operand(MCInst &Inst, unsigned Val,
2195*9880d681SAndroid Build Coastguard Worker                            uint64_t Address, const void *Decoder) {
2196*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2197*9880d681SAndroid Build Coastguard Worker 
2198*9880d681SAndroid Build Coastguard Worker   unsigned add = fieldFromInstruction(Val, 12, 1);
2199*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 0, 12);
2200*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 13, 4);
2201*9880d681SAndroid Build Coastguard Worker 
2202*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
2203*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2204*9880d681SAndroid Build Coastguard Worker 
2205*9880d681SAndroid Build Coastguard Worker   if (!add) imm *= -1;
2206*9880d681SAndroid Build Coastguard Worker   if (imm == 0 && !add) imm = INT32_MIN;
2207*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
2208*9880d681SAndroid Build Coastguard Worker   if (Rn == 15)
2209*9880d681SAndroid Build Coastguard Worker     tryAddingPcLoadReferenceComment(Address, Address + imm + 8, Decoder);
2210*9880d681SAndroid Build Coastguard Worker 
2211*9880d681SAndroid Build Coastguard Worker   return S;
2212*9880d681SAndroid Build Coastguard Worker }
2213*9880d681SAndroid Build Coastguard Worker 
DecodeAddrMode5Operand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)2214*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode5Operand(MCInst &Inst, unsigned Val,
2215*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
2216*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2217*9880d681SAndroid Build Coastguard Worker 
2218*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 9, 4);
2219*9880d681SAndroid Build Coastguard Worker   // U == 1 to add imm, 0 to subtract it.
2220*9880d681SAndroid Build Coastguard Worker   unsigned U = fieldFromInstruction(Val, 8, 1);
2221*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 0, 8);
2222*9880d681SAndroid Build Coastguard Worker 
2223*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
2224*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2225*9880d681SAndroid Build Coastguard Worker 
2226*9880d681SAndroid Build Coastguard Worker   if (U)
2227*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(ARM_AM::getAM5Opc(ARM_AM::add, imm)));
2228*9880d681SAndroid Build Coastguard Worker   else
2229*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(ARM_AM::getAM5Opc(ARM_AM::sub, imm)));
2230*9880d681SAndroid Build Coastguard Worker 
2231*9880d681SAndroid Build Coastguard Worker   return S;
2232*9880d681SAndroid Build Coastguard Worker }
2233*9880d681SAndroid Build Coastguard Worker 
DecodeAddrMode5FP16Operand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)2234*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode5FP16Operand(MCInst &Inst, unsigned Val,
2235*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
2236*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2237*9880d681SAndroid Build Coastguard Worker 
2238*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 9, 4);
2239*9880d681SAndroid Build Coastguard Worker   // U == 1 to add imm, 0 to subtract it.
2240*9880d681SAndroid Build Coastguard Worker   unsigned U = fieldFromInstruction(Val, 8, 1);
2241*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 0, 8);
2242*9880d681SAndroid Build Coastguard Worker 
2243*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
2244*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2245*9880d681SAndroid Build Coastguard Worker 
2246*9880d681SAndroid Build Coastguard Worker   if (U)
2247*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(ARM_AM::getAM5FP16Opc(ARM_AM::add, imm)));
2248*9880d681SAndroid Build Coastguard Worker   else
2249*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(ARM_AM::getAM5FP16Opc(ARM_AM::sub, imm)));
2250*9880d681SAndroid Build Coastguard Worker 
2251*9880d681SAndroid Build Coastguard Worker   return S;
2252*9880d681SAndroid Build Coastguard Worker }
2253*9880d681SAndroid Build Coastguard Worker 
DecodeAddrMode7Operand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)2254*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode7Operand(MCInst &Inst, unsigned Val,
2255*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
2256*9880d681SAndroid Build Coastguard Worker   return DecodeGPRRegisterClass(Inst, Val, Address, Decoder);
2257*9880d681SAndroid Build Coastguard Worker }
2258*9880d681SAndroid Build Coastguard Worker 
2259*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeT2BInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2260*9880d681SAndroid Build Coastguard Worker DecodeT2BInstruction(MCInst &Inst, unsigned Insn,
2261*9880d681SAndroid Build Coastguard Worker                      uint64_t Address, const void *Decoder) {
2262*9880d681SAndroid Build Coastguard Worker   DecodeStatus Status = MCDisassembler::Success;
2263*9880d681SAndroid Build Coastguard Worker 
2264*9880d681SAndroid Build Coastguard Worker   // Note the J1 and J2 values are from the encoded instruction.  So here
2265*9880d681SAndroid Build Coastguard Worker   // change them to I1 and I2 values via as documented:
2266*9880d681SAndroid Build Coastguard Worker   // I1 = NOT(J1 EOR S);
2267*9880d681SAndroid Build Coastguard Worker   // I2 = NOT(J2 EOR S);
2268*9880d681SAndroid Build Coastguard Worker   // and build the imm32 with one trailing zero as documented:
2269*9880d681SAndroid Build Coastguard Worker   // imm32 = SignExtend(S:I1:I2:imm10:imm11:'0', 32);
2270*9880d681SAndroid Build Coastguard Worker   unsigned S = fieldFromInstruction(Insn, 26, 1);
2271*9880d681SAndroid Build Coastguard Worker   unsigned J1 = fieldFromInstruction(Insn, 13, 1);
2272*9880d681SAndroid Build Coastguard Worker   unsigned J2 = fieldFromInstruction(Insn, 11, 1);
2273*9880d681SAndroid Build Coastguard Worker   unsigned I1 = !(J1 ^ S);
2274*9880d681SAndroid Build Coastguard Worker   unsigned I2 = !(J2 ^ S);
2275*9880d681SAndroid Build Coastguard Worker   unsigned imm10 = fieldFromInstruction(Insn, 16, 10);
2276*9880d681SAndroid Build Coastguard Worker   unsigned imm11 = fieldFromInstruction(Insn, 0, 11);
2277*9880d681SAndroid Build Coastguard Worker   unsigned tmp = (S << 23) | (I1 << 22) | (I2 << 21) | (imm10 << 11) | imm11;
2278*9880d681SAndroid Build Coastguard Worker   int imm32 = SignExtend32<25>(tmp << 1);
2279*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address, Address + imm32 + 4,
2280*9880d681SAndroid Build Coastguard Worker                                 true, 4, Inst, Decoder))
2281*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imm32));
2282*9880d681SAndroid Build Coastguard Worker 
2283*9880d681SAndroid Build Coastguard Worker   return Status;
2284*9880d681SAndroid Build Coastguard Worker }
2285*9880d681SAndroid Build Coastguard Worker 
2286*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeBranchImmInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2287*9880d681SAndroid Build Coastguard Worker DecodeBranchImmInstruction(MCInst &Inst, unsigned Insn,
2288*9880d681SAndroid Build Coastguard Worker                            uint64_t Address, const void *Decoder) {
2289*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2290*9880d681SAndroid Build Coastguard Worker 
2291*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
2292*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 24) << 2;
2293*9880d681SAndroid Build Coastguard Worker 
2294*9880d681SAndroid Build Coastguard Worker   if (pred == 0xF) {
2295*9880d681SAndroid Build Coastguard Worker     Inst.setOpcode(ARM::BLXi);
2296*9880d681SAndroid Build Coastguard Worker     imm |= fieldFromInstruction(Insn, 24, 1) << 1;
2297*9880d681SAndroid Build Coastguard Worker     if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<26>(imm) + 8,
2298*9880d681SAndroid Build Coastguard Worker                                   true, 4, Inst, Decoder))
2299*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(SignExtend32<26>(imm)));
2300*9880d681SAndroid Build Coastguard Worker     return S;
2301*9880d681SAndroid Build Coastguard Worker   }
2302*9880d681SAndroid Build Coastguard Worker 
2303*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<26>(imm) + 8,
2304*9880d681SAndroid Build Coastguard Worker                                 true, 4, Inst, Decoder))
2305*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(SignExtend32<26>(imm)));
2306*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
2307*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2308*9880d681SAndroid Build Coastguard Worker 
2309*9880d681SAndroid Build Coastguard Worker   return S;
2310*9880d681SAndroid Build Coastguard Worker }
2311*9880d681SAndroid Build Coastguard Worker 
2312*9880d681SAndroid Build Coastguard Worker 
DecodeAddrMode6Operand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)2313*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeAddrMode6Operand(MCInst &Inst, unsigned Val,
2314*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
2315*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2316*9880d681SAndroid Build Coastguard Worker 
2317*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Val, 0, 4);
2318*9880d681SAndroid Build Coastguard Worker   unsigned align = fieldFromInstruction(Val, 4, 2);
2319*9880d681SAndroid Build Coastguard Worker 
2320*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
2321*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2322*9880d681SAndroid Build Coastguard Worker   if (!align)
2323*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(0));
2324*9880d681SAndroid Build Coastguard Worker   else
2325*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(4 << align));
2326*9880d681SAndroid Build Coastguard Worker 
2327*9880d681SAndroid Build Coastguard Worker   return S;
2328*9880d681SAndroid Build Coastguard Worker }
2329*9880d681SAndroid Build Coastguard Worker 
DecodeVLDInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2330*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDInstruction(MCInst &Inst, unsigned Insn,
2331*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
2332*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2333*9880d681SAndroid Build Coastguard Worker 
2334*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
2335*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
2336*9880d681SAndroid Build Coastguard Worker   unsigned wb = fieldFromInstruction(Insn, 16, 4);
2337*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
2338*9880d681SAndroid Build Coastguard Worker   Rn |= fieldFromInstruction(Insn, 4, 2) << 4;
2339*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
2340*9880d681SAndroid Build Coastguard Worker 
2341*9880d681SAndroid Build Coastguard Worker   // First output register
2342*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2343*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q16: case ARM::VLD1q32: case ARM::VLD1q64: case ARM::VLD1q8:
2344*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q16wb_fixed: case ARM::VLD1q16wb_register:
2345*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q32wb_fixed: case ARM::VLD1q32wb_register:
2346*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q64wb_fixed: case ARM::VLD1q64wb_register:
2347*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q8wb_fixed: case ARM::VLD1q8wb_register:
2348*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2d16: case ARM::VLD2d32: case ARM::VLD2d8:
2349*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2d16wb_fixed: case ARM::VLD2d16wb_register:
2350*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2d32wb_fixed: case ARM::VLD2d32wb_register:
2351*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2d8wb_fixed: case ARM::VLD2d8wb_register:
2352*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPairRegisterClass(Inst, Rd, Address, Decoder)))
2353*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2354*9880d681SAndroid Build Coastguard Worker     break;
2355*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b16:
2356*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b32:
2357*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b8:
2358*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b16wb_fixed:
2359*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b16wb_register:
2360*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b32wb_fixed:
2361*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b32wb_register:
2362*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b8wb_fixed:
2363*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b8wb_register:
2364*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPairSpacedRegisterClass(Inst, Rd, Address, Decoder)))
2365*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2366*9880d681SAndroid Build Coastguard Worker     break;
2367*9880d681SAndroid Build Coastguard Worker   default:
2368*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
2369*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2370*9880d681SAndroid Build Coastguard Worker   }
2371*9880d681SAndroid Build Coastguard Worker 
2372*9880d681SAndroid Build Coastguard Worker   // Second output register
2373*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2374*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d8:
2375*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d16:
2376*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d32:
2377*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d8_UPD:
2378*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d16_UPD:
2379*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d32_UPD:
2380*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d8:
2381*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d16:
2382*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d32:
2383*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d8_UPD:
2384*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d16_UPD:
2385*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d32_UPD:
2386*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder)))
2387*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2388*9880d681SAndroid Build Coastguard Worker       break;
2389*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q8:
2390*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q16:
2391*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q32:
2392*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q8_UPD:
2393*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q16_UPD:
2394*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q32_UPD:
2395*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q8:
2396*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q16:
2397*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q32:
2398*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q8_UPD:
2399*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q16_UPD:
2400*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q32_UPD:
2401*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)))
2402*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2403*9880d681SAndroid Build Coastguard Worker     default:
2404*9880d681SAndroid Build Coastguard Worker       break;
2405*9880d681SAndroid Build Coastguard Worker   }
2406*9880d681SAndroid Build Coastguard Worker 
2407*9880d681SAndroid Build Coastguard Worker   // Third output register
2408*9880d681SAndroid Build Coastguard Worker   switch(Inst.getOpcode()) {
2409*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d8:
2410*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d16:
2411*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d32:
2412*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d8_UPD:
2413*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d16_UPD:
2414*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d32_UPD:
2415*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d8:
2416*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d16:
2417*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d32:
2418*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d8_UPD:
2419*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d16_UPD:
2420*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d32_UPD:
2421*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)))
2422*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2423*9880d681SAndroid Build Coastguard Worker       break;
2424*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q8:
2425*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q16:
2426*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q32:
2427*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q8_UPD:
2428*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q16_UPD:
2429*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q32_UPD:
2430*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q8:
2431*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q16:
2432*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q32:
2433*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q8_UPD:
2434*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q16_UPD:
2435*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q32_UPD:
2436*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder)))
2437*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2438*9880d681SAndroid Build Coastguard Worker       break;
2439*9880d681SAndroid Build Coastguard Worker     default:
2440*9880d681SAndroid Build Coastguard Worker       break;
2441*9880d681SAndroid Build Coastguard Worker   }
2442*9880d681SAndroid Build Coastguard Worker 
2443*9880d681SAndroid Build Coastguard Worker   // Fourth output register
2444*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2445*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d8:
2446*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d16:
2447*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d32:
2448*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d8_UPD:
2449*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d16_UPD:
2450*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d32_UPD:
2451*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder)))
2452*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2453*9880d681SAndroid Build Coastguard Worker       break;
2454*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q8:
2455*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q16:
2456*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q32:
2457*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q8_UPD:
2458*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q16_UPD:
2459*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q32_UPD:
2460*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder)))
2461*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2462*9880d681SAndroid Build Coastguard Worker       break;
2463*9880d681SAndroid Build Coastguard Worker     default:
2464*9880d681SAndroid Build Coastguard Worker       break;
2465*9880d681SAndroid Build Coastguard Worker   }
2466*9880d681SAndroid Build Coastguard Worker 
2467*9880d681SAndroid Build Coastguard Worker   // Writeback operand
2468*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2469*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d8wb_fixed:
2470*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d16wb_fixed:
2471*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d32wb_fixed:
2472*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d64wb_fixed:
2473*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d8wb_register:
2474*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d16wb_register:
2475*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d32wb_register:
2476*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d64wb_register:
2477*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1q8wb_fixed:
2478*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1q16wb_fixed:
2479*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1q32wb_fixed:
2480*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1q64wb_fixed:
2481*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1q8wb_register:
2482*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1q16wb_register:
2483*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1q32wb_register:
2484*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1q64wb_register:
2485*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d8Twb_fixed:
2486*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d8Twb_register:
2487*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d16Twb_fixed:
2488*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d16Twb_register:
2489*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d32Twb_fixed:
2490*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d32Twb_register:
2491*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d64Twb_fixed:
2492*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d64Twb_register:
2493*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d8Qwb_fixed:
2494*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d8Qwb_register:
2495*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d16Qwb_fixed:
2496*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d16Qwb_register:
2497*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d32Qwb_fixed:
2498*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d32Qwb_register:
2499*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d64Qwb_fixed:
2500*9880d681SAndroid Build Coastguard Worker     case ARM::VLD1d64Qwb_register:
2501*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2d8wb_fixed:
2502*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2d16wb_fixed:
2503*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2d32wb_fixed:
2504*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2q8wb_fixed:
2505*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2q16wb_fixed:
2506*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2q32wb_fixed:
2507*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2d8wb_register:
2508*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2d16wb_register:
2509*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2d32wb_register:
2510*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2q8wb_register:
2511*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2q16wb_register:
2512*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2q32wb_register:
2513*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2b8wb_fixed:
2514*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2b16wb_fixed:
2515*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2b32wb_fixed:
2516*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2b8wb_register:
2517*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2b16wb_register:
2518*9880d681SAndroid Build Coastguard Worker     case ARM::VLD2b32wb_register:
2519*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(0));
2520*9880d681SAndroid Build Coastguard Worker       break;
2521*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d8_UPD:
2522*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d16_UPD:
2523*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3d32_UPD:
2524*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q8_UPD:
2525*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q16_UPD:
2526*9880d681SAndroid Build Coastguard Worker     case ARM::VLD3q32_UPD:
2527*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d8_UPD:
2528*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d16_UPD:
2529*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4d32_UPD:
2530*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q8_UPD:
2531*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q16_UPD:
2532*9880d681SAndroid Build Coastguard Worker     case ARM::VLD4q32_UPD:
2533*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, wb, Address, Decoder)))
2534*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2535*9880d681SAndroid Build Coastguard Worker       break;
2536*9880d681SAndroid Build Coastguard Worker     default:
2537*9880d681SAndroid Build Coastguard Worker       break;
2538*9880d681SAndroid Build Coastguard Worker   }
2539*9880d681SAndroid Build Coastguard Worker 
2540*9880d681SAndroid Build Coastguard Worker   // AddrMode6 Base (register+alignment)
2541*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeAddrMode6Operand(Inst, Rn, Address, Decoder)))
2542*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2543*9880d681SAndroid Build Coastguard Worker 
2544*9880d681SAndroid Build Coastguard Worker   // AddrMode6 Offset (register)
2545*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2546*9880d681SAndroid Build Coastguard Worker   default:
2547*9880d681SAndroid Build Coastguard Worker     // The below have been updated to have explicit am6offset split
2548*9880d681SAndroid Build Coastguard Worker     // between fixed and register offset. For those instructions not
2549*9880d681SAndroid Build Coastguard Worker     // yet updated, we need to add an additional reg0 operand for the
2550*9880d681SAndroid Build Coastguard Worker     // fixed variant.
2551*9880d681SAndroid Build Coastguard Worker     //
2552*9880d681SAndroid Build Coastguard Worker     // The fixed offset encodes as Rm == 0xd, so we check for that.
2553*9880d681SAndroid Build Coastguard Worker     if (Rm == 0xd) {
2554*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(0));
2555*9880d681SAndroid Build Coastguard Worker       break;
2556*9880d681SAndroid Build Coastguard Worker     }
2557*9880d681SAndroid Build Coastguard Worker     // Fall through to handle the register offset variant.
2558*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d8wb_fixed:
2559*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d16wb_fixed:
2560*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d32wb_fixed:
2561*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d64wb_fixed:
2562*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d8Twb_fixed:
2563*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d16Twb_fixed:
2564*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d32Twb_fixed:
2565*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d64Twb_fixed:
2566*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d8Qwb_fixed:
2567*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d16Qwb_fixed:
2568*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d32Qwb_fixed:
2569*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d64Qwb_fixed:
2570*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d8wb_register:
2571*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d16wb_register:
2572*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d32wb_register:
2573*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1d64wb_register:
2574*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q8wb_fixed:
2575*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q16wb_fixed:
2576*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q32wb_fixed:
2577*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q64wb_fixed:
2578*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q8wb_register:
2579*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q16wb_register:
2580*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q32wb_register:
2581*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1q64wb_register:
2582*9880d681SAndroid Build Coastguard Worker     // The fixed offset post-increment encodes Rm == 0xd. The no-writeback
2583*9880d681SAndroid Build Coastguard Worker     // variant encodes Rm == 0xf. Anything else is a register offset post-
2584*9880d681SAndroid Build Coastguard Worker     // increment and we need to add the register operand to the instruction.
2585*9880d681SAndroid Build Coastguard Worker     if (Rm != 0xD && Rm != 0xF &&
2586*9880d681SAndroid Build Coastguard Worker         !Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
2587*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2588*9880d681SAndroid Build Coastguard Worker     break;
2589*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2d8wb_fixed:
2590*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2d16wb_fixed:
2591*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2d32wb_fixed:
2592*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b8wb_fixed:
2593*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b16wb_fixed:
2594*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2b32wb_fixed:
2595*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2q8wb_fixed:
2596*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2q16wb_fixed:
2597*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2q32wb_fixed:
2598*9880d681SAndroid Build Coastguard Worker     break;
2599*9880d681SAndroid Build Coastguard Worker   }
2600*9880d681SAndroid Build Coastguard Worker 
2601*9880d681SAndroid Build Coastguard Worker   return S;
2602*9880d681SAndroid Build Coastguard Worker }
2603*9880d681SAndroid Build Coastguard Worker 
DecodeVLDST1Instruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2604*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDST1Instruction(MCInst &Inst, unsigned Insn,
2605*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
2606*9880d681SAndroid Build Coastguard Worker   unsigned type = fieldFromInstruction(Insn, 8, 4);
2607*9880d681SAndroid Build Coastguard Worker   unsigned align = fieldFromInstruction(Insn, 4, 2);
2608*9880d681SAndroid Build Coastguard Worker   if (type == 6 && (align & 2)) return MCDisassembler::Fail;
2609*9880d681SAndroid Build Coastguard Worker   if (type == 7 && (align & 2)) return MCDisassembler::Fail;
2610*9880d681SAndroid Build Coastguard Worker   if (type == 10 && align == 3) return MCDisassembler::Fail;
2611*9880d681SAndroid Build Coastguard Worker 
2612*9880d681SAndroid Build Coastguard Worker   unsigned load = fieldFromInstruction(Insn, 21, 1);
2613*9880d681SAndroid Build Coastguard Worker   return load ? DecodeVLDInstruction(Inst, Insn, Address, Decoder)
2614*9880d681SAndroid Build Coastguard Worker               : DecodeVSTInstruction(Inst, Insn, Address, Decoder);
2615*9880d681SAndroid Build Coastguard Worker }
2616*9880d681SAndroid Build Coastguard Worker 
DecodeVLDST2Instruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2617*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDST2Instruction(MCInst &Inst, unsigned Insn,
2618*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
2619*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 6, 2);
2620*9880d681SAndroid Build Coastguard Worker   if (size == 3) return MCDisassembler::Fail;
2621*9880d681SAndroid Build Coastguard Worker 
2622*9880d681SAndroid Build Coastguard Worker   unsigned type = fieldFromInstruction(Insn, 8, 4);
2623*9880d681SAndroid Build Coastguard Worker   unsigned align = fieldFromInstruction(Insn, 4, 2);
2624*9880d681SAndroid Build Coastguard Worker   if (type == 8 && align == 3) return MCDisassembler::Fail;
2625*9880d681SAndroid Build Coastguard Worker   if (type == 9 && align == 3) return MCDisassembler::Fail;
2626*9880d681SAndroid Build Coastguard Worker 
2627*9880d681SAndroid Build Coastguard Worker   unsigned load = fieldFromInstruction(Insn, 21, 1);
2628*9880d681SAndroid Build Coastguard Worker   return load ? DecodeVLDInstruction(Inst, Insn, Address, Decoder)
2629*9880d681SAndroid Build Coastguard Worker               : DecodeVSTInstruction(Inst, Insn, Address, Decoder);
2630*9880d681SAndroid Build Coastguard Worker }
2631*9880d681SAndroid Build Coastguard Worker 
DecodeVLDST3Instruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2632*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDST3Instruction(MCInst &Inst, unsigned Insn,
2633*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
2634*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 6, 2);
2635*9880d681SAndroid Build Coastguard Worker   if (size == 3) return MCDisassembler::Fail;
2636*9880d681SAndroid Build Coastguard Worker 
2637*9880d681SAndroid Build Coastguard Worker   unsigned align = fieldFromInstruction(Insn, 4, 2);
2638*9880d681SAndroid Build Coastguard Worker   if (align & 2) return MCDisassembler::Fail;
2639*9880d681SAndroid Build Coastguard Worker 
2640*9880d681SAndroid Build Coastguard Worker   unsigned load = fieldFromInstruction(Insn, 21, 1);
2641*9880d681SAndroid Build Coastguard Worker   return load ? DecodeVLDInstruction(Inst, Insn, Address, Decoder)
2642*9880d681SAndroid Build Coastguard Worker               : DecodeVSTInstruction(Inst, Insn, Address, Decoder);
2643*9880d681SAndroid Build Coastguard Worker }
2644*9880d681SAndroid Build Coastguard Worker 
DecodeVLDST4Instruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2645*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLDST4Instruction(MCInst &Inst, unsigned Insn,
2646*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
2647*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 6, 2);
2648*9880d681SAndroid Build Coastguard Worker   if (size == 3) return MCDisassembler::Fail;
2649*9880d681SAndroid Build Coastguard Worker 
2650*9880d681SAndroid Build Coastguard Worker   unsigned load = fieldFromInstruction(Insn, 21, 1);
2651*9880d681SAndroid Build Coastguard Worker   return load ? DecodeVLDInstruction(Inst, Insn, Address, Decoder)
2652*9880d681SAndroid Build Coastguard Worker               : DecodeVSTInstruction(Inst, Insn, Address, Decoder);
2653*9880d681SAndroid Build Coastguard Worker }
2654*9880d681SAndroid Build Coastguard Worker 
DecodeVSTInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2655*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVSTInstruction(MCInst &Inst, unsigned Insn,
2656*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
2657*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2658*9880d681SAndroid Build Coastguard Worker 
2659*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
2660*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
2661*9880d681SAndroid Build Coastguard Worker   unsigned wb = fieldFromInstruction(Insn, 16, 4);
2662*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
2663*9880d681SAndroid Build Coastguard Worker   Rn |= fieldFromInstruction(Insn, 4, 2) << 4;
2664*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
2665*9880d681SAndroid Build Coastguard Worker 
2666*9880d681SAndroid Build Coastguard Worker   // Writeback Operand
2667*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2668*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d8wb_fixed:
2669*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d16wb_fixed:
2670*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d32wb_fixed:
2671*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d64wb_fixed:
2672*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d8wb_register:
2673*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d16wb_register:
2674*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d32wb_register:
2675*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d64wb_register:
2676*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q8wb_fixed:
2677*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q16wb_fixed:
2678*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q32wb_fixed:
2679*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q64wb_fixed:
2680*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q8wb_register:
2681*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q16wb_register:
2682*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q32wb_register:
2683*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q64wb_register:
2684*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d8Twb_fixed:
2685*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d16Twb_fixed:
2686*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d32Twb_fixed:
2687*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d64Twb_fixed:
2688*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d8Twb_register:
2689*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d16Twb_register:
2690*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d32Twb_register:
2691*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d64Twb_register:
2692*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d8Qwb_fixed:
2693*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d16Qwb_fixed:
2694*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d32Qwb_fixed:
2695*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d64Qwb_fixed:
2696*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d8Qwb_register:
2697*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d16Qwb_register:
2698*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d32Qwb_register:
2699*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d64Qwb_register:
2700*9880d681SAndroid Build Coastguard Worker     case ARM::VST2d8wb_fixed:
2701*9880d681SAndroid Build Coastguard Worker     case ARM::VST2d16wb_fixed:
2702*9880d681SAndroid Build Coastguard Worker     case ARM::VST2d32wb_fixed:
2703*9880d681SAndroid Build Coastguard Worker     case ARM::VST2d8wb_register:
2704*9880d681SAndroid Build Coastguard Worker     case ARM::VST2d16wb_register:
2705*9880d681SAndroid Build Coastguard Worker     case ARM::VST2d32wb_register:
2706*9880d681SAndroid Build Coastguard Worker     case ARM::VST2q8wb_fixed:
2707*9880d681SAndroid Build Coastguard Worker     case ARM::VST2q16wb_fixed:
2708*9880d681SAndroid Build Coastguard Worker     case ARM::VST2q32wb_fixed:
2709*9880d681SAndroid Build Coastguard Worker     case ARM::VST2q8wb_register:
2710*9880d681SAndroid Build Coastguard Worker     case ARM::VST2q16wb_register:
2711*9880d681SAndroid Build Coastguard Worker     case ARM::VST2q32wb_register:
2712*9880d681SAndroid Build Coastguard Worker     case ARM::VST2b8wb_fixed:
2713*9880d681SAndroid Build Coastguard Worker     case ARM::VST2b16wb_fixed:
2714*9880d681SAndroid Build Coastguard Worker     case ARM::VST2b32wb_fixed:
2715*9880d681SAndroid Build Coastguard Worker     case ARM::VST2b8wb_register:
2716*9880d681SAndroid Build Coastguard Worker     case ARM::VST2b16wb_register:
2717*9880d681SAndroid Build Coastguard Worker     case ARM::VST2b32wb_register:
2718*9880d681SAndroid Build Coastguard Worker       if (Rm == 0xF)
2719*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2720*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(0));
2721*9880d681SAndroid Build Coastguard Worker       break;
2722*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d8_UPD:
2723*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d16_UPD:
2724*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d32_UPD:
2725*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q8_UPD:
2726*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q16_UPD:
2727*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q32_UPD:
2728*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d8_UPD:
2729*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d16_UPD:
2730*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d32_UPD:
2731*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q8_UPD:
2732*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q16_UPD:
2733*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q32_UPD:
2734*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, wb, Address, Decoder)))
2735*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2736*9880d681SAndroid Build Coastguard Worker       break;
2737*9880d681SAndroid Build Coastguard Worker     default:
2738*9880d681SAndroid Build Coastguard Worker       break;
2739*9880d681SAndroid Build Coastguard Worker   }
2740*9880d681SAndroid Build Coastguard Worker 
2741*9880d681SAndroid Build Coastguard Worker   // AddrMode6 Base (register+alignment)
2742*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeAddrMode6Operand(Inst, Rn, Address, Decoder)))
2743*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2744*9880d681SAndroid Build Coastguard Worker 
2745*9880d681SAndroid Build Coastguard Worker   // AddrMode6 Offset (register)
2746*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2747*9880d681SAndroid Build Coastguard Worker     default:
2748*9880d681SAndroid Build Coastguard Worker       if (Rm == 0xD)
2749*9880d681SAndroid Build Coastguard Worker         Inst.addOperand(MCOperand::createReg(0));
2750*9880d681SAndroid Build Coastguard Worker       else if (Rm != 0xF) {
2751*9880d681SAndroid Build Coastguard Worker         if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
2752*9880d681SAndroid Build Coastguard Worker           return MCDisassembler::Fail;
2753*9880d681SAndroid Build Coastguard Worker       }
2754*9880d681SAndroid Build Coastguard Worker       break;
2755*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d8wb_fixed:
2756*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d16wb_fixed:
2757*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d32wb_fixed:
2758*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d64wb_fixed:
2759*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q8wb_fixed:
2760*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q16wb_fixed:
2761*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q32wb_fixed:
2762*9880d681SAndroid Build Coastguard Worker     case ARM::VST1q64wb_fixed:
2763*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d8Twb_fixed:
2764*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d16Twb_fixed:
2765*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d32Twb_fixed:
2766*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d64Twb_fixed:
2767*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d8Qwb_fixed:
2768*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d16Qwb_fixed:
2769*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d32Qwb_fixed:
2770*9880d681SAndroid Build Coastguard Worker     case ARM::VST1d64Qwb_fixed:
2771*9880d681SAndroid Build Coastguard Worker     case ARM::VST2d8wb_fixed:
2772*9880d681SAndroid Build Coastguard Worker     case ARM::VST2d16wb_fixed:
2773*9880d681SAndroid Build Coastguard Worker     case ARM::VST2d32wb_fixed:
2774*9880d681SAndroid Build Coastguard Worker     case ARM::VST2q8wb_fixed:
2775*9880d681SAndroid Build Coastguard Worker     case ARM::VST2q16wb_fixed:
2776*9880d681SAndroid Build Coastguard Worker     case ARM::VST2q32wb_fixed:
2777*9880d681SAndroid Build Coastguard Worker     case ARM::VST2b8wb_fixed:
2778*9880d681SAndroid Build Coastguard Worker     case ARM::VST2b16wb_fixed:
2779*9880d681SAndroid Build Coastguard Worker     case ARM::VST2b32wb_fixed:
2780*9880d681SAndroid Build Coastguard Worker       break;
2781*9880d681SAndroid Build Coastguard Worker   }
2782*9880d681SAndroid Build Coastguard Worker 
2783*9880d681SAndroid Build Coastguard Worker 
2784*9880d681SAndroid Build Coastguard Worker   // First input register
2785*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2786*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q16:
2787*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q32:
2788*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q64:
2789*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q8:
2790*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q16wb_fixed:
2791*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q16wb_register:
2792*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q32wb_fixed:
2793*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q32wb_register:
2794*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q64wb_fixed:
2795*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q64wb_register:
2796*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q8wb_fixed:
2797*9880d681SAndroid Build Coastguard Worker   case ARM::VST1q8wb_register:
2798*9880d681SAndroid Build Coastguard Worker   case ARM::VST2d16:
2799*9880d681SAndroid Build Coastguard Worker   case ARM::VST2d32:
2800*9880d681SAndroid Build Coastguard Worker   case ARM::VST2d8:
2801*9880d681SAndroid Build Coastguard Worker   case ARM::VST2d16wb_fixed:
2802*9880d681SAndroid Build Coastguard Worker   case ARM::VST2d16wb_register:
2803*9880d681SAndroid Build Coastguard Worker   case ARM::VST2d32wb_fixed:
2804*9880d681SAndroid Build Coastguard Worker   case ARM::VST2d32wb_register:
2805*9880d681SAndroid Build Coastguard Worker   case ARM::VST2d8wb_fixed:
2806*9880d681SAndroid Build Coastguard Worker   case ARM::VST2d8wb_register:
2807*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPairRegisterClass(Inst, Rd, Address, Decoder)))
2808*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2809*9880d681SAndroid Build Coastguard Worker     break;
2810*9880d681SAndroid Build Coastguard Worker   case ARM::VST2b16:
2811*9880d681SAndroid Build Coastguard Worker   case ARM::VST2b32:
2812*9880d681SAndroid Build Coastguard Worker   case ARM::VST2b8:
2813*9880d681SAndroid Build Coastguard Worker   case ARM::VST2b16wb_fixed:
2814*9880d681SAndroid Build Coastguard Worker   case ARM::VST2b16wb_register:
2815*9880d681SAndroid Build Coastguard Worker   case ARM::VST2b32wb_fixed:
2816*9880d681SAndroid Build Coastguard Worker   case ARM::VST2b32wb_register:
2817*9880d681SAndroid Build Coastguard Worker   case ARM::VST2b8wb_fixed:
2818*9880d681SAndroid Build Coastguard Worker   case ARM::VST2b8wb_register:
2819*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPairSpacedRegisterClass(Inst, Rd, Address, Decoder)))
2820*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2821*9880d681SAndroid Build Coastguard Worker     break;
2822*9880d681SAndroid Build Coastguard Worker   default:
2823*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
2824*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2825*9880d681SAndroid Build Coastguard Worker   }
2826*9880d681SAndroid Build Coastguard Worker 
2827*9880d681SAndroid Build Coastguard Worker   // Second input register
2828*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2829*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d8:
2830*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d16:
2831*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d32:
2832*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d8_UPD:
2833*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d16_UPD:
2834*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d32_UPD:
2835*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d8:
2836*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d16:
2837*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d32:
2838*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d8_UPD:
2839*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d16_UPD:
2840*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d32_UPD:
2841*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder)))
2842*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2843*9880d681SAndroid Build Coastguard Worker       break;
2844*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q8:
2845*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q16:
2846*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q32:
2847*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q8_UPD:
2848*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q16_UPD:
2849*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q32_UPD:
2850*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q8:
2851*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q16:
2852*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q32:
2853*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q8_UPD:
2854*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q16_UPD:
2855*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q32_UPD:
2856*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)))
2857*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2858*9880d681SAndroid Build Coastguard Worker       break;
2859*9880d681SAndroid Build Coastguard Worker     default:
2860*9880d681SAndroid Build Coastguard Worker       break;
2861*9880d681SAndroid Build Coastguard Worker   }
2862*9880d681SAndroid Build Coastguard Worker 
2863*9880d681SAndroid Build Coastguard Worker   // Third input register
2864*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2865*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d8:
2866*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d16:
2867*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d32:
2868*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d8_UPD:
2869*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d16_UPD:
2870*9880d681SAndroid Build Coastguard Worker     case ARM::VST3d32_UPD:
2871*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d8:
2872*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d16:
2873*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d32:
2874*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d8_UPD:
2875*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d16_UPD:
2876*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d32_UPD:
2877*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)))
2878*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2879*9880d681SAndroid Build Coastguard Worker       break;
2880*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q8:
2881*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q16:
2882*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q32:
2883*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q8_UPD:
2884*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q16_UPD:
2885*9880d681SAndroid Build Coastguard Worker     case ARM::VST3q32_UPD:
2886*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q8:
2887*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q16:
2888*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q32:
2889*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q8_UPD:
2890*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q16_UPD:
2891*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q32_UPD:
2892*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder)))
2893*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2894*9880d681SAndroid Build Coastguard Worker       break;
2895*9880d681SAndroid Build Coastguard Worker     default:
2896*9880d681SAndroid Build Coastguard Worker       break;
2897*9880d681SAndroid Build Coastguard Worker   }
2898*9880d681SAndroid Build Coastguard Worker 
2899*9880d681SAndroid Build Coastguard Worker   // Fourth input register
2900*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2901*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d8:
2902*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d16:
2903*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d32:
2904*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d8_UPD:
2905*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d16_UPD:
2906*9880d681SAndroid Build Coastguard Worker     case ARM::VST4d32_UPD:
2907*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder)))
2908*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2909*9880d681SAndroid Build Coastguard Worker       break;
2910*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q8:
2911*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q16:
2912*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q32:
2913*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q8_UPD:
2914*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q16_UPD:
2915*9880d681SAndroid Build Coastguard Worker     case ARM::VST4q32_UPD:
2916*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder)))
2917*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
2918*9880d681SAndroid Build Coastguard Worker       break;
2919*9880d681SAndroid Build Coastguard Worker     default:
2920*9880d681SAndroid Build Coastguard Worker       break;
2921*9880d681SAndroid Build Coastguard Worker   }
2922*9880d681SAndroid Build Coastguard Worker 
2923*9880d681SAndroid Build Coastguard Worker   return S;
2924*9880d681SAndroid Build Coastguard Worker }
2925*9880d681SAndroid Build Coastguard Worker 
DecodeVLD1DupInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2926*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD1DupInstruction(MCInst &Inst, unsigned Insn,
2927*9880d681SAndroid Build Coastguard Worker                                     uint64_t Address, const void *Decoder) {
2928*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2929*9880d681SAndroid Build Coastguard Worker 
2930*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
2931*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
2932*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
2933*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
2934*9880d681SAndroid Build Coastguard Worker   unsigned align = fieldFromInstruction(Insn, 4, 1);
2935*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 6, 2);
2936*9880d681SAndroid Build Coastguard Worker 
2937*9880d681SAndroid Build Coastguard Worker   if (size == 0 && align == 1)
2938*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2939*9880d681SAndroid Build Coastguard Worker   align *= (1 << size);
2940*9880d681SAndroid Build Coastguard Worker 
2941*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2942*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1DUPq16: case ARM::VLD1DUPq32: case ARM::VLD1DUPq8:
2943*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1DUPq16wb_fixed: case ARM::VLD1DUPq16wb_register:
2944*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1DUPq32wb_fixed: case ARM::VLD1DUPq32wb_register:
2945*9880d681SAndroid Build Coastguard Worker   case ARM::VLD1DUPq8wb_fixed: case ARM::VLD1DUPq8wb_register:
2946*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPairRegisterClass(Inst, Rd, Address, Decoder)))
2947*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2948*9880d681SAndroid Build Coastguard Worker     break;
2949*9880d681SAndroid Build Coastguard Worker   default:
2950*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
2951*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2952*9880d681SAndroid Build Coastguard Worker     break;
2953*9880d681SAndroid Build Coastguard Worker   }
2954*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
2955*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
2956*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2957*9880d681SAndroid Build Coastguard Worker   }
2958*9880d681SAndroid Build Coastguard Worker 
2959*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
2960*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2961*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
2962*9880d681SAndroid Build Coastguard Worker 
2963*9880d681SAndroid Build Coastguard Worker   // The fixed offset post-increment encodes Rm == 0xd. The no-writeback
2964*9880d681SAndroid Build Coastguard Worker   // variant encodes Rm == 0xf. Anything else is a register offset post-
2965*9880d681SAndroid Build Coastguard Worker   // increment and we need to add the register operand to the instruction.
2966*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xD && Rm != 0xF &&
2967*9880d681SAndroid Build Coastguard Worker       !Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
2968*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
2969*9880d681SAndroid Build Coastguard Worker 
2970*9880d681SAndroid Build Coastguard Worker   return S;
2971*9880d681SAndroid Build Coastguard Worker }
2972*9880d681SAndroid Build Coastguard Worker 
DecodeVLD2DupInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)2973*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn,
2974*9880d681SAndroid Build Coastguard Worker                                     uint64_t Address, const void *Decoder) {
2975*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
2976*9880d681SAndroid Build Coastguard Worker 
2977*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
2978*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
2979*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
2980*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
2981*9880d681SAndroid Build Coastguard Worker   unsigned align = fieldFromInstruction(Insn, 4, 1);
2982*9880d681SAndroid Build Coastguard Worker   unsigned size = 1 << fieldFromInstruction(Insn, 6, 2);
2983*9880d681SAndroid Build Coastguard Worker   align *= 2*size;
2984*9880d681SAndroid Build Coastguard Worker 
2985*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
2986*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2DUPd16: case ARM::VLD2DUPd32: case ARM::VLD2DUPd8:
2987*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2DUPd16wb_fixed: case ARM::VLD2DUPd16wb_register:
2988*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2DUPd32wb_fixed: case ARM::VLD2DUPd32wb_register:
2989*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2DUPd8wb_fixed: case ARM::VLD2DUPd8wb_register:
2990*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPairRegisterClass(Inst, Rd, Address, Decoder)))
2991*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2992*9880d681SAndroid Build Coastguard Worker     break;
2993*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2DUPd16x2: case ARM::VLD2DUPd32x2: case ARM::VLD2DUPd8x2:
2994*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2DUPd16x2wb_fixed: case ARM::VLD2DUPd16x2wb_register:
2995*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2DUPd32x2wb_fixed: case ARM::VLD2DUPd32x2wb_register:
2996*9880d681SAndroid Build Coastguard Worker   case ARM::VLD2DUPd8x2wb_fixed: case ARM::VLD2DUPd8x2wb_register:
2997*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPairSpacedRegisterClass(Inst, Rd, Address, Decoder)))
2998*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
2999*9880d681SAndroid Build Coastguard Worker     break;
3000*9880d681SAndroid Build Coastguard Worker   default:
3001*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
3002*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3003*9880d681SAndroid Build Coastguard Worker     break;
3004*9880d681SAndroid Build Coastguard Worker   }
3005*9880d681SAndroid Build Coastguard Worker 
3006*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF)
3007*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(0));
3008*9880d681SAndroid Build Coastguard Worker 
3009*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3010*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3011*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
3012*9880d681SAndroid Build Coastguard Worker 
3013*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xD && Rm != 0xF) {
3014*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
3015*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3016*9880d681SAndroid Build Coastguard Worker   }
3017*9880d681SAndroid Build Coastguard Worker 
3018*9880d681SAndroid Build Coastguard Worker   return S;
3019*9880d681SAndroid Build Coastguard Worker }
3020*9880d681SAndroid Build Coastguard Worker 
DecodeVLD3DupInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3021*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD3DupInstruction(MCInst &Inst, unsigned Insn,
3022*9880d681SAndroid Build Coastguard Worker                                     uint64_t Address, const void *Decoder) {
3023*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3024*9880d681SAndroid Build Coastguard Worker 
3025*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
3026*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
3027*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
3028*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
3029*9880d681SAndroid Build Coastguard Worker   unsigned inc = fieldFromInstruction(Insn, 5, 1) + 1;
3030*9880d681SAndroid Build Coastguard Worker 
3031*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
3032*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3033*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder)))
3034*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3035*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder)))
3036*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3037*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
3038*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3039*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3040*9880d681SAndroid Build Coastguard Worker   }
3041*9880d681SAndroid Build Coastguard Worker 
3042*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3043*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3044*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(0));
3045*9880d681SAndroid Build Coastguard Worker 
3046*9880d681SAndroid Build Coastguard Worker   if (Rm == 0xD)
3047*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(0));
3048*9880d681SAndroid Build Coastguard Worker   else if (Rm != 0xF) {
3049*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
3050*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3051*9880d681SAndroid Build Coastguard Worker   }
3052*9880d681SAndroid Build Coastguard Worker 
3053*9880d681SAndroid Build Coastguard Worker   return S;
3054*9880d681SAndroid Build Coastguard Worker }
3055*9880d681SAndroid Build Coastguard Worker 
DecodeVLD4DupInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3056*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD4DupInstruction(MCInst &Inst, unsigned Insn,
3057*9880d681SAndroid Build Coastguard Worker                                     uint64_t Address, const void *Decoder) {
3058*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3059*9880d681SAndroid Build Coastguard Worker 
3060*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
3061*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
3062*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
3063*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
3064*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 6, 2);
3065*9880d681SAndroid Build Coastguard Worker   unsigned inc = fieldFromInstruction(Insn, 5, 1) + 1;
3066*9880d681SAndroid Build Coastguard Worker   unsigned align = fieldFromInstruction(Insn, 4, 1);
3067*9880d681SAndroid Build Coastguard Worker 
3068*9880d681SAndroid Build Coastguard Worker   if (size == 0x3) {
3069*9880d681SAndroid Build Coastguard Worker     if (align == 0)
3070*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3071*9880d681SAndroid Build Coastguard Worker     align = 16;
3072*9880d681SAndroid Build Coastguard Worker   } else {
3073*9880d681SAndroid Build Coastguard Worker     if (size == 2) {
3074*9880d681SAndroid Build Coastguard Worker       align *= 8;
3075*9880d681SAndroid Build Coastguard Worker     } else {
3076*9880d681SAndroid Build Coastguard Worker       size = 1 << size;
3077*9880d681SAndroid Build Coastguard Worker       align *= 4*size;
3078*9880d681SAndroid Build Coastguard Worker     }
3079*9880d681SAndroid Build Coastguard Worker   }
3080*9880d681SAndroid Build Coastguard Worker 
3081*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
3082*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3083*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder)))
3084*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3085*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder)))
3086*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3087*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+3*inc)%32, Address, Decoder)))
3088*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3089*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
3090*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3091*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3092*9880d681SAndroid Build Coastguard Worker   }
3093*9880d681SAndroid Build Coastguard Worker 
3094*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3095*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3096*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
3097*9880d681SAndroid Build Coastguard Worker 
3098*9880d681SAndroid Build Coastguard Worker   if (Rm == 0xD)
3099*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(0));
3100*9880d681SAndroid Build Coastguard Worker   else if (Rm != 0xF) {
3101*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
3102*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3103*9880d681SAndroid Build Coastguard Worker   }
3104*9880d681SAndroid Build Coastguard Worker 
3105*9880d681SAndroid Build Coastguard Worker   return S;
3106*9880d681SAndroid Build Coastguard Worker }
3107*9880d681SAndroid Build Coastguard Worker 
3108*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeNEONModImmInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3109*9880d681SAndroid Build Coastguard Worker DecodeNEONModImmInstruction(MCInst &Inst, unsigned Insn,
3110*9880d681SAndroid Build Coastguard Worker                             uint64_t Address, const void *Decoder) {
3111*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3112*9880d681SAndroid Build Coastguard Worker 
3113*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
3114*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
3115*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 4);
3116*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 16, 3) << 4;
3117*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 24, 1) << 7;
3118*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 8, 4) << 8;
3119*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 5, 1) << 12;
3120*9880d681SAndroid Build Coastguard Worker   unsigned Q = fieldFromInstruction(Insn, 6, 1);
3121*9880d681SAndroid Build Coastguard Worker 
3122*9880d681SAndroid Build Coastguard Worker   if (Q) {
3123*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder)))
3124*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3125*9880d681SAndroid Build Coastguard Worker   } else {
3126*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
3127*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3128*9880d681SAndroid Build Coastguard Worker   }
3129*9880d681SAndroid Build Coastguard Worker 
3130*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3131*9880d681SAndroid Build Coastguard Worker 
3132*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
3133*9880d681SAndroid Build Coastguard Worker     case ARM::VORRiv4i16:
3134*9880d681SAndroid Build Coastguard Worker     case ARM::VORRiv2i32:
3135*9880d681SAndroid Build Coastguard Worker     case ARM::VBICiv4i16:
3136*9880d681SAndroid Build Coastguard Worker     case ARM::VBICiv2i32:
3137*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
3138*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
3139*9880d681SAndroid Build Coastguard Worker       break;
3140*9880d681SAndroid Build Coastguard Worker     case ARM::VORRiv8i16:
3141*9880d681SAndroid Build Coastguard Worker     case ARM::VORRiv4i32:
3142*9880d681SAndroid Build Coastguard Worker     case ARM::VBICiv8i16:
3143*9880d681SAndroid Build Coastguard Worker     case ARM::VBICiv4i32:
3144*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder)))
3145*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
3146*9880d681SAndroid Build Coastguard Worker       break;
3147*9880d681SAndroid Build Coastguard Worker     default:
3148*9880d681SAndroid Build Coastguard Worker       break;
3149*9880d681SAndroid Build Coastguard Worker   }
3150*9880d681SAndroid Build Coastguard Worker 
3151*9880d681SAndroid Build Coastguard Worker   return S;
3152*9880d681SAndroid Build Coastguard Worker }
3153*9880d681SAndroid Build Coastguard Worker 
DecodeVSHLMaxInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3154*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVSHLMaxInstruction(MCInst &Inst, unsigned Insn,
3155*9880d681SAndroid Build Coastguard Worker                                         uint64_t Address, const void *Decoder) {
3156*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3157*9880d681SAndroid Build Coastguard Worker 
3158*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
3159*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
3160*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
3161*9880d681SAndroid Build Coastguard Worker   Rm |= fieldFromInstruction(Insn, 5, 1) << 4;
3162*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 18, 2);
3163*9880d681SAndroid Build Coastguard Worker 
3164*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder)))
3165*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3166*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder)))
3167*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3168*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(8 << size));
3169*9880d681SAndroid Build Coastguard Worker 
3170*9880d681SAndroid Build Coastguard Worker   return S;
3171*9880d681SAndroid Build Coastguard Worker }
3172*9880d681SAndroid Build Coastguard Worker 
DecodeShiftRight8Imm(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3173*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeShiftRight8Imm(MCInst &Inst, unsigned Val,
3174*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
3175*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(8 - Val));
3176*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3177*9880d681SAndroid Build Coastguard Worker }
3178*9880d681SAndroid Build Coastguard Worker 
DecodeShiftRight16Imm(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3179*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeShiftRight16Imm(MCInst &Inst, unsigned Val,
3180*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
3181*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(16 - Val));
3182*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3183*9880d681SAndroid Build Coastguard Worker }
3184*9880d681SAndroid Build Coastguard Worker 
DecodeShiftRight32Imm(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3185*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeShiftRight32Imm(MCInst &Inst, unsigned Val,
3186*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
3187*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(32 - Val));
3188*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3189*9880d681SAndroid Build Coastguard Worker }
3190*9880d681SAndroid Build Coastguard Worker 
DecodeShiftRight64Imm(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3191*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeShiftRight64Imm(MCInst &Inst, unsigned Val,
3192*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
3193*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(64 - Val));
3194*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3195*9880d681SAndroid Build Coastguard Worker }
3196*9880d681SAndroid Build Coastguard Worker 
DecodeTBLInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3197*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeTBLInstruction(MCInst &Inst, unsigned Insn,
3198*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
3199*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3200*9880d681SAndroid Build Coastguard Worker 
3201*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
3202*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
3203*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
3204*9880d681SAndroid Build Coastguard Worker   Rn |= fieldFromInstruction(Insn, 7, 1) << 4;
3205*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
3206*9880d681SAndroid Build Coastguard Worker   Rm |= fieldFromInstruction(Insn, 5, 1) << 4;
3207*9880d681SAndroid Build Coastguard Worker   unsigned op = fieldFromInstruction(Insn, 6, 1);
3208*9880d681SAndroid Build Coastguard Worker 
3209*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
3210*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3211*9880d681SAndroid Build Coastguard Worker   if (op) {
3212*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
3213*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail; // Writeback
3214*9880d681SAndroid Build Coastguard Worker   }
3215*9880d681SAndroid Build Coastguard Worker 
3216*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
3217*9880d681SAndroid Build Coastguard Worker   case ARM::VTBL2:
3218*9880d681SAndroid Build Coastguard Worker   case ARM::VTBX2:
3219*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPairRegisterClass(Inst, Rn, Address, Decoder)))
3220*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3221*9880d681SAndroid Build Coastguard Worker     break;
3222*9880d681SAndroid Build Coastguard Worker   default:
3223*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeDPRRegisterClass(Inst, Rn, Address, Decoder)))
3224*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3225*9880d681SAndroid Build Coastguard Worker   }
3226*9880d681SAndroid Build Coastguard Worker 
3227*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder)))
3228*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3229*9880d681SAndroid Build Coastguard Worker 
3230*9880d681SAndroid Build Coastguard Worker   return S;
3231*9880d681SAndroid Build Coastguard Worker }
3232*9880d681SAndroid Build Coastguard Worker 
DecodeThumbAddSpecialReg(MCInst & Inst,uint16_t Insn,uint64_t Address,const void * Decoder)3233*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddSpecialReg(MCInst &Inst, uint16_t Insn,
3234*9880d681SAndroid Build Coastguard Worker                                      uint64_t Address, const void *Decoder) {
3235*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3236*9880d681SAndroid Build Coastguard Worker 
3237*9880d681SAndroid Build Coastguard Worker   unsigned dst = fieldFromInstruction(Insn, 8, 3);
3238*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 8);
3239*9880d681SAndroid Build Coastguard Worker 
3240*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodetGPRRegisterClass(Inst, dst, Address, Decoder)))
3241*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3242*9880d681SAndroid Build Coastguard Worker 
3243*9880d681SAndroid Build Coastguard Worker   switch(Inst.getOpcode()) {
3244*9880d681SAndroid Build Coastguard Worker     default:
3245*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3246*9880d681SAndroid Build Coastguard Worker     case ARM::tADR:
3247*9880d681SAndroid Build Coastguard Worker       break; // tADR does not explicitly represent the PC as an operand.
3248*9880d681SAndroid Build Coastguard Worker     case ARM::tADDrSPi:
3249*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(ARM::SP));
3250*9880d681SAndroid Build Coastguard Worker       break;
3251*9880d681SAndroid Build Coastguard Worker   }
3252*9880d681SAndroid Build Coastguard Worker 
3253*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3254*9880d681SAndroid Build Coastguard Worker   return S;
3255*9880d681SAndroid Build Coastguard Worker }
3256*9880d681SAndroid Build Coastguard Worker 
DecodeThumbBROperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3257*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbBROperand(MCInst &Inst, unsigned Val,
3258*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
3259*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<12>(Val<<1) + 4,
3260*9880d681SAndroid Build Coastguard Worker                                 true, 2, Inst, Decoder))
3261*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(SignExtend32<12>(Val << 1)));
3262*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3263*9880d681SAndroid Build Coastguard Worker }
3264*9880d681SAndroid Build Coastguard Worker 
DecodeT2BROperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3265*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2BROperand(MCInst &Inst, unsigned Val,
3266*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
3267*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<21>(Val) + 4,
3268*9880d681SAndroid Build Coastguard Worker                                 true, 4, Inst, Decoder))
3269*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(SignExtend32<21>(Val)));
3270*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3271*9880d681SAndroid Build Coastguard Worker }
3272*9880d681SAndroid Build Coastguard Worker 
DecodeThumbCmpBROperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3273*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbCmpBROperand(MCInst &Inst, unsigned Val,
3274*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
3275*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address, Address + (Val<<1) + 4,
3276*9880d681SAndroid Build Coastguard Worker                                 true, 2, Inst, Decoder))
3277*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(Val << 1));
3278*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3279*9880d681SAndroid Build Coastguard Worker }
3280*9880d681SAndroid Build Coastguard Worker 
DecodeThumbAddrModeRR(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3281*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddrModeRR(MCInst &Inst, unsigned Val,
3282*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
3283*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3284*9880d681SAndroid Build Coastguard Worker 
3285*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 0, 3);
3286*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Val, 3, 3);
3287*9880d681SAndroid Build Coastguard Worker 
3288*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodetGPRRegisterClass(Inst, Rn, Address, Decoder)))
3289*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3290*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodetGPRRegisterClass(Inst, Rm, Address, Decoder)))
3291*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3292*9880d681SAndroid Build Coastguard Worker 
3293*9880d681SAndroid Build Coastguard Worker   return S;
3294*9880d681SAndroid Build Coastguard Worker }
3295*9880d681SAndroid Build Coastguard Worker 
DecodeThumbAddrModeIS(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3296*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddrModeIS(MCInst &Inst, unsigned Val,
3297*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
3298*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3299*9880d681SAndroid Build Coastguard Worker 
3300*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 0, 3);
3301*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 3, 5);
3302*9880d681SAndroid Build Coastguard Worker 
3303*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodetGPRRegisterClass(Inst, Rn, Address, Decoder)))
3304*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3305*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3306*9880d681SAndroid Build Coastguard Worker 
3307*9880d681SAndroid Build Coastguard Worker   return S;
3308*9880d681SAndroid Build Coastguard Worker }
3309*9880d681SAndroid Build Coastguard Worker 
DecodeThumbAddrModePC(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3310*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddrModePC(MCInst &Inst, unsigned Val,
3311*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
3312*9880d681SAndroid Build Coastguard Worker   unsigned imm = Val << 2;
3313*9880d681SAndroid Build Coastguard Worker 
3314*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3315*9880d681SAndroid Build Coastguard Worker   tryAddingPcLoadReferenceComment(Address, (Address & ~2u) + imm + 4, Decoder);
3316*9880d681SAndroid Build Coastguard Worker 
3317*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3318*9880d681SAndroid Build Coastguard Worker }
3319*9880d681SAndroid Build Coastguard Worker 
DecodeThumbAddrModeSP(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3320*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddrModeSP(MCInst &Inst, unsigned Val,
3321*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
3322*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(ARM::SP));
3323*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Val));
3324*9880d681SAndroid Build Coastguard Worker 
3325*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3326*9880d681SAndroid Build Coastguard Worker }
3327*9880d681SAndroid Build Coastguard Worker 
DecodeT2AddrModeSOReg(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3328*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeSOReg(MCInst &Inst, unsigned Val,
3329*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
3330*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3331*9880d681SAndroid Build Coastguard Worker 
3332*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 6, 4);
3333*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Val, 2, 4);
3334*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 0, 2);
3335*9880d681SAndroid Build Coastguard Worker 
3336*9880d681SAndroid Build Coastguard Worker   // Thumb stores cannot use PC as dest register.
3337*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
3338*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRHs:
3339*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRBs:
3340*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRs:
3341*9880d681SAndroid Build Coastguard Worker     if (Rn == 15)
3342*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3343*9880d681SAndroid Build Coastguard Worker   default:
3344*9880d681SAndroid Build Coastguard Worker     break;
3345*9880d681SAndroid Build Coastguard Worker   }
3346*9880d681SAndroid Build Coastguard Worker 
3347*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3348*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3349*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
3350*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3351*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3352*9880d681SAndroid Build Coastguard Worker 
3353*9880d681SAndroid Build Coastguard Worker   return S;
3354*9880d681SAndroid Build Coastguard Worker }
3355*9880d681SAndroid Build Coastguard Worker 
DecodeT2LoadShift(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3356*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
3357*9880d681SAndroid Build Coastguard Worker                               uint64_t Address, const void *Decoder) {
3358*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3359*9880d681SAndroid Build Coastguard Worker 
3360*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
3361*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
3362*9880d681SAndroid Build Coastguard Worker 
3363*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
3364*9880d681SAndroid Build Coastguard Worker     ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
3365*9880d681SAndroid Build Coastguard Worker 
3366*9880d681SAndroid Build Coastguard Worker   bool hasMP = featureBits[ARM::FeatureMP];
3367*9880d681SAndroid Build Coastguard Worker   bool hasV7Ops = featureBits[ARM::HasV7Ops];
3368*9880d681SAndroid Build Coastguard Worker 
3369*9880d681SAndroid Build Coastguard Worker   if (Rn == 15) {
3370*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
3371*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRBs:
3372*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRBpci);
3373*9880d681SAndroid Build Coastguard Worker       break;
3374*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRHs:
3375*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRHpci);
3376*9880d681SAndroid Build Coastguard Worker       break;
3377*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSHs:
3378*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRSHpci);
3379*9880d681SAndroid Build Coastguard Worker       break;
3380*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSBs:
3381*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRSBpci);
3382*9880d681SAndroid Build Coastguard Worker       break;
3383*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRs:
3384*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRpci);
3385*9880d681SAndroid Build Coastguard Worker       break;
3386*9880d681SAndroid Build Coastguard Worker     case ARM::t2PLDs:
3387*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLDpci);
3388*9880d681SAndroid Build Coastguard Worker       break;
3389*9880d681SAndroid Build Coastguard Worker     case ARM::t2PLIs:
3390*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLIpci);
3391*9880d681SAndroid Build Coastguard Worker       break;
3392*9880d681SAndroid Build Coastguard Worker     default:
3393*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3394*9880d681SAndroid Build Coastguard Worker     }
3395*9880d681SAndroid Build Coastguard Worker 
3396*9880d681SAndroid Build Coastguard Worker     return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
3397*9880d681SAndroid Build Coastguard Worker   }
3398*9880d681SAndroid Build Coastguard Worker 
3399*9880d681SAndroid Build Coastguard Worker   if (Rt == 15) {
3400*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
3401*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSHs:
3402*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3403*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRHs:
3404*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLDWs);
3405*9880d681SAndroid Build Coastguard Worker       break;
3406*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSBs:
3407*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLIs);
3408*9880d681SAndroid Build Coastguard Worker     default:
3409*9880d681SAndroid Build Coastguard Worker       break;
3410*9880d681SAndroid Build Coastguard Worker     }
3411*9880d681SAndroid Build Coastguard Worker   }
3412*9880d681SAndroid Build Coastguard Worker 
3413*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
3414*9880d681SAndroid Build Coastguard Worker     case ARM::t2PLDs:
3415*9880d681SAndroid Build Coastguard Worker       break;
3416*9880d681SAndroid Build Coastguard Worker     case ARM::t2PLIs:
3417*9880d681SAndroid Build Coastguard Worker       if (!hasV7Ops)
3418*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
3419*9880d681SAndroid Build Coastguard Worker       break;
3420*9880d681SAndroid Build Coastguard Worker     case ARM::t2PLDWs:
3421*9880d681SAndroid Build Coastguard Worker       if (!hasV7Ops || !hasMP)
3422*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
3423*9880d681SAndroid Build Coastguard Worker       break;
3424*9880d681SAndroid Build Coastguard Worker     default:
3425*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
3426*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
3427*9880d681SAndroid Build Coastguard Worker   }
3428*9880d681SAndroid Build Coastguard Worker 
3429*9880d681SAndroid Build Coastguard Worker   unsigned addrmode = fieldFromInstruction(Insn, 4, 2);
3430*9880d681SAndroid Build Coastguard Worker   addrmode |= fieldFromInstruction(Insn, 0, 4) << 2;
3431*9880d681SAndroid Build Coastguard Worker   addrmode |= fieldFromInstruction(Insn, 16, 4) << 6;
3432*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder)))
3433*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3434*9880d681SAndroid Build Coastguard Worker 
3435*9880d681SAndroid Build Coastguard Worker   return S;
3436*9880d681SAndroid Build Coastguard Worker }
3437*9880d681SAndroid Build Coastguard Worker 
DecodeT2LoadImm8(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3438*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
3439*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void* Decoder) {
3440*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3441*9880d681SAndroid Build Coastguard Worker 
3442*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
3443*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
3444*9880d681SAndroid Build Coastguard Worker   unsigned U = fieldFromInstruction(Insn, 9, 1);
3445*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 8);
3446*9880d681SAndroid Build Coastguard Worker   imm |= (U << 8);
3447*9880d681SAndroid Build Coastguard Worker   imm |= (Rn << 9);
3448*9880d681SAndroid Build Coastguard Worker   unsigned add = fieldFromInstruction(Insn, 9, 1);
3449*9880d681SAndroid Build Coastguard Worker 
3450*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
3451*9880d681SAndroid Build Coastguard Worker     ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
3452*9880d681SAndroid Build Coastguard Worker 
3453*9880d681SAndroid Build Coastguard Worker   bool hasMP = featureBits[ARM::FeatureMP];
3454*9880d681SAndroid Build Coastguard Worker   bool hasV7Ops = featureBits[ARM::HasV7Ops];
3455*9880d681SAndroid Build Coastguard Worker 
3456*9880d681SAndroid Build Coastguard Worker   if (Rn == 15) {
3457*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
3458*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRi8:
3459*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRpci);
3460*9880d681SAndroid Build Coastguard Worker       break;
3461*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRBi8:
3462*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRBpci);
3463*9880d681SAndroid Build Coastguard Worker       break;
3464*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSBi8:
3465*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRSBpci);
3466*9880d681SAndroid Build Coastguard Worker       break;
3467*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRHi8:
3468*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRHpci);
3469*9880d681SAndroid Build Coastguard Worker       break;
3470*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSHi8:
3471*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRSHpci);
3472*9880d681SAndroid Build Coastguard Worker       break;
3473*9880d681SAndroid Build Coastguard Worker     case ARM::t2PLDi8:
3474*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLDpci);
3475*9880d681SAndroid Build Coastguard Worker       break;
3476*9880d681SAndroid Build Coastguard Worker     case ARM::t2PLIi8:
3477*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLIpci);
3478*9880d681SAndroid Build Coastguard Worker       break;
3479*9880d681SAndroid Build Coastguard Worker     default:
3480*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3481*9880d681SAndroid Build Coastguard Worker     }
3482*9880d681SAndroid Build Coastguard Worker     return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
3483*9880d681SAndroid Build Coastguard Worker   }
3484*9880d681SAndroid Build Coastguard Worker 
3485*9880d681SAndroid Build Coastguard Worker   if (Rt == 15) {
3486*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
3487*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSHi8:
3488*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3489*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRHi8:
3490*9880d681SAndroid Build Coastguard Worker       if (!add)
3491*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::t2PLDWi8);
3492*9880d681SAndroid Build Coastguard Worker       break;
3493*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSBi8:
3494*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLIi8);
3495*9880d681SAndroid Build Coastguard Worker       break;
3496*9880d681SAndroid Build Coastguard Worker     default:
3497*9880d681SAndroid Build Coastguard Worker       break;
3498*9880d681SAndroid Build Coastguard Worker     }
3499*9880d681SAndroid Build Coastguard Worker   }
3500*9880d681SAndroid Build Coastguard Worker 
3501*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
3502*9880d681SAndroid Build Coastguard Worker   case ARM::t2PLDi8:
3503*9880d681SAndroid Build Coastguard Worker     break;
3504*9880d681SAndroid Build Coastguard Worker   case ARM::t2PLIi8:
3505*9880d681SAndroid Build Coastguard Worker     if (!hasV7Ops)
3506*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3507*9880d681SAndroid Build Coastguard Worker     break;
3508*9880d681SAndroid Build Coastguard Worker   case ARM::t2PLDWi8:
3509*9880d681SAndroid Build Coastguard Worker       if (!hasV7Ops || !hasMP)
3510*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
3511*9880d681SAndroid Build Coastguard Worker       break;
3512*9880d681SAndroid Build Coastguard Worker   default:
3513*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
3514*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3515*9880d681SAndroid Build Coastguard Worker   }
3516*9880d681SAndroid Build Coastguard Worker 
3517*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2AddrModeImm8(Inst, imm, Address, Decoder)))
3518*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3519*9880d681SAndroid Build Coastguard Worker   return S;
3520*9880d681SAndroid Build Coastguard Worker }
3521*9880d681SAndroid Build Coastguard Worker 
DecodeT2LoadImm12(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3522*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
3523*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void* Decoder) {
3524*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3525*9880d681SAndroid Build Coastguard Worker 
3526*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
3527*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
3528*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 12);
3529*9880d681SAndroid Build Coastguard Worker   imm |= (Rn << 13);
3530*9880d681SAndroid Build Coastguard Worker 
3531*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
3532*9880d681SAndroid Build Coastguard Worker     ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
3533*9880d681SAndroid Build Coastguard Worker 
3534*9880d681SAndroid Build Coastguard Worker   bool hasMP = featureBits[ARM::FeatureMP];
3535*9880d681SAndroid Build Coastguard Worker   bool hasV7Ops = featureBits[ARM::HasV7Ops];
3536*9880d681SAndroid Build Coastguard Worker 
3537*9880d681SAndroid Build Coastguard Worker   if (Rn == 15) {
3538*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
3539*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRi12:
3540*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRpci);
3541*9880d681SAndroid Build Coastguard Worker       break;
3542*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRHi12:
3543*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRHpci);
3544*9880d681SAndroid Build Coastguard Worker       break;
3545*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSHi12:
3546*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRSHpci);
3547*9880d681SAndroid Build Coastguard Worker       break;
3548*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRBi12:
3549*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRBpci);
3550*9880d681SAndroid Build Coastguard Worker       break;
3551*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSBi12:
3552*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRSBpci);
3553*9880d681SAndroid Build Coastguard Worker       break;
3554*9880d681SAndroid Build Coastguard Worker     case ARM::t2PLDi12:
3555*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLDpci);
3556*9880d681SAndroid Build Coastguard Worker       break;
3557*9880d681SAndroid Build Coastguard Worker     case ARM::t2PLIi12:
3558*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLIpci);
3559*9880d681SAndroid Build Coastguard Worker       break;
3560*9880d681SAndroid Build Coastguard Worker     default:
3561*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3562*9880d681SAndroid Build Coastguard Worker     }
3563*9880d681SAndroid Build Coastguard Worker     return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
3564*9880d681SAndroid Build Coastguard Worker   }
3565*9880d681SAndroid Build Coastguard Worker 
3566*9880d681SAndroid Build Coastguard Worker   if (Rt == 15) {
3567*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
3568*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSHi12:
3569*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3570*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRHi12:
3571*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLDWi12);
3572*9880d681SAndroid Build Coastguard Worker       break;
3573*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSBi12:
3574*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2PLIi12);
3575*9880d681SAndroid Build Coastguard Worker       break;
3576*9880d681SAndroid Build Coastguard Worker     default:
3577*9880d681SAndroid Build Coastguard Worker       break;
3578*9880d681SAndroid Build Coastguard Worker     }
3579*9880d681SAndroid Build Coastguard Worker   }
3580*9880d681SAndroid Build Coastguard Worker 
3581*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
3582*9880d681SAndroid Build Coastguard Worker   case ARM::t2PLDi12:
3583*9880d681SAndroid Build Coastguard Worker     break;
3584*9880d681SAndroid Build Coastguard Worker   case ARM::t2PLIi12:
3585*9880d681SAndroid Build Coastguard Worker     if (!hasV7Ops)
3586*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3587*9880d681SAndroid Build Coastguard Worker     break;
3588*9880d681SAndroid Build Coastguard Worker   case ARM::t2PLDWi12:
3589*9880d681SAndroid Build Coastguard Worker       if (!hasV7Ops || !hasMP)
3590*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
3591*9880d681SAndroid Build Coastguard Worker       break;
3592*9880d681SAndroid Build Coastguard Worker   default:
3593*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
3594*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3595*9880d681SAndroid Build Coastguard Worker   }
3596*9880d681SAndroid Build Coastguard Worker 
3597*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2AddrModeImm12(Inst, imm, Address, Decoder)))
3598*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3599*9880d681SAndroid Build Coastguard Worker   return S;
3600*9880d681SAndroid Build Coastguard Worker }
3601*9880d681SAndroid Build Coastguard Worker 
DecodeT2LoadT(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3602*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadT(MCInst &Inst, unsigned Insn,
3603*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void* Decoder) {
3604*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3605*9880d681SAndroid Build Coastguard Worker 
3606*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
3607*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
3608*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 8);
3609*9880d681SAndroid Build Coastguard Worker   imm |= (Rn << 9);
3610*9880d681SAndroid Build Coastguard Worker 
3611*9880d681SAndroid Build Coastguard Worker   if (Rn == 15) {
3612*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
3613*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRT:
3614*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRpci);
3615*9880d681SAndroid Build Coastguard Worker       break;
3616*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRBT:
3617*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRBpci);
3618*9880d681SAndroid Build Coastguard Worker       break;
3619*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRHT:
3620*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRHpci);
3621*9880d681SAndroid Build Coastguard Worker       break;
3622*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSBT:
3623*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRSBpci);
3624*9880d681SAndroid Build Coastguard Worker       break;
3625*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSHT:
3626*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRSHpci);
3627*9880d681SAndroid Build Coastguard Worker       break;
3628*9880d681SAndroid Build Coastguard Worker     default:
3629*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3630*9880d681SAndroid Build Coastguard Worker     }
3631*9880d681SAndroid Build Coastguard Worker     return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
3632*9880d681SAndroid Build Coastguard Worker   }
3633*9880d681SAndroid Build Coastguard Worker 
3634*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
3635*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3636*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2AddrModeImm8(Inst, imm, Address, Decoder)))
3637*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3638*9880d681SAndroid Build Coastguard Worker   return S;
3639*9880d681SAndroid Build Coastguard Worker }
3640*9880d681SAndroid Build Coastguard Worker 
DecodeT2LoadLabel(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3641*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
3642*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void* Decoder) {
3643*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3644*9880d681SAndroid Build Coastguard Worker 
3645*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
3646*9880d681SAndroid Build Coastguard Worker   unsigned U = fieldFromInstruction(Insn, 23, 1);
3647*9880d681SAndroid Build Coastguard Worker   int imm = fieldFromInstruction(Insn, 0, 12);
3648*9880d681SAndroid Build Coastguard Worker 
3649*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
3650*9880d681SAndroid Build Coastguard Worker     ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
3651*9880d681SAndroid Build Coastguard Worker 
3652*9880d681SAndroid Build Coastguard Worker   bool hasV7Ops = featureBits[ARM::HasV7Ops];
3653*9880d681SAndroid Build Coastguard Worker 
3654*9880d681SAndroid Build Coastguard Worker   if (Rt == 15) {
3655*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
3656*9880d681SAndroid Build Coastguard Worker       case ARM::t2LDRBpci:
3657*9880d681SAndroid Build Coastguard Worker       case ARM::t2LDRHpci:
3658*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::t2PLDpci);
3659*9880d681SAndroid Build Coastguard Worker         break;
3660*9880d681SAndroid Build Coastguard Worker       case ARM::t2LDRSBpci:
3661*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::t2PLIpci);
3662*9880d681SAndroid Build Coastguard Worker         break;
3663*9880d681SAndroid Build Coastguard Worker       case ARM::t2LDRSHpci:
3664*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
3665*9880d681SAndroid Build Coastguard Worker       default:
3666*9880d681SAndroid Build Coastguard Worker         break;
3667*9880d681SAndroid Build Coastguard Worker     }
3668*9880d681SAndroid Build Coastguard Worker   }
3669*9880d681SAndroid Build Coastguard Worker 
3670*9880d681SAndroid Build Coastguard Worker   switch(Inst.getOpcode()) {
3671*9880d681SAndroid Build Coastguard Worker   case ARM::t2PLDpci:
3672*9880d681SAndroid Build Coastguard Worker     break;
3673*9880d681SAndroid Build Coastguard Worker   case ARM::t2PLIpci:
3674*9880d681SAndroid Build Coastguard Worker     if (!hasV7Ops)
3675*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3676*9880d681SAndroid Build Coastguard Worker     break;
3677*9880d681SAndroid Build Coastguard Worker   default:
3678*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
3679*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3680*9880d681SAndroid Build Coastguard Worker   }
3681*9880d681SAndroid Build Coastguard Worker 
3682*9880d681SAndroid Build Coastguard Worker   if (!U) {
3683*9880d681SAndroid Build Coastguard Worker     // Special case for #-0.
3684*9880d681SAndroid Build Coastguard Worker     if (imm == 0)
3685*9880d681SAndroid Build Coastguard Worker       imm = INT32_MIN;
3686*9880d681SAndroid Build Coastguard Worker     else
3687*9880d681SAndroid Build Coastguard Worker       imm = -imm;
3688*9880d681SAndroid Build Coastguard Worker   }
3689*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3690*9880d681SAndroid Build Coastguard Worker 
3691*9880d681SAndroid Build Coastguard Worker   return S;
3692*9880d681SAndroid Build Coastguard Worker }
3693*9880d681SAndroid Build Coastguard Worker 
DecodeT2Imm8S4(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3694*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2Imm8S4(MCInst &Inst, unsigned Val,
3695*9880d681SAndroid Build Coastguard Worker                            uint64_t Address, const void *Decoder) {
3696*9880d681SAndroid Build Coastguard Worker   if (Val == 0)
3697*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(INT32_MIN));
3698*9880d681SAndroid Build Coastguard Worker   else {
3699*9880d681SAndroid Build Coastguard Worker     int imm = Val & 0xFF;
3700*9880d681SAndroid Build Coastguard Worker 
3701*9880d681SAndroid Build Coastguard Worker     if (!(Val & 0x100)) imm *= -1;
3702*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imm * 4));
3703*9880d681SAndroid Build Coastguard Worker   }
3704*9880d681SAndroid Build Coastguard Worker 
3705*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3706*9880d681SAndroid Build Coastguard Worker }
3707*9880d681SAndroid Build Coastguard Worker 
DecodeT2AddrModeImm8s4(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3708*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeImm8s4(MCInst &Inst, unsigned Val,
3709*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
3710*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3711*9880d681SAndroid Build Coastguard Worker 
3712*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 9, 4);
3713*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 0, 9);
3714*9880d681SAndroid Build Coastguard Worker 
3715*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3716*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3717*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2Imm8S4(Inst, imm, Address, Decoder)))
3718*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3719*9880d681SAndroid Build Coastguard Worker 
3720*9880d681SAndroid Build Coastguard Worker   return S;
3721*9880d681SAndroid Build Coastguard Worker }
3722*9880d681SAndroid Build Coastguard Worker 
DecodeT2AddrModeImm0_1020s4(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3723*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeImm0_1020s4(MCInst &Inst,unsigned Val,
3724*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
3725*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3726*9880d681SAndroid Build Coastguard Worker 
3727*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 8, 4);
3728*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 0, 8);
3729*9880d681SAndroid Build Coastguard Worker 
3730*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
3731*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3732*9880d681SAndroid Build Coastguard Worker 
3733*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3734*9880d681SAndroid Build Coastguard Worker 
3735*9880d681SAndroid Build Coastguard Worker   return S;
3736*9880d681SAndroid Build Coastguard Worker }
3737*9880d681SAndroid Build Coastguard Worker 
DecodeT2Imm8(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3738*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2Imm8(MCInst &Inst, unsigned Val,
3739*9880d681SAndroid Build Coastguard Worker                          uint64_t Address, const void *Decoder) {
3740*9880d681SAndroid Build Coastguard Worker   int imm = Val & 0xFF;
3741*9880d681SAndroid Build Coastguard Worker   if (Val == 0)
3742*9880d681SAndroid Build Coastguard Worker     imm = INT32_MIN;
3743*9880d681SAndroid Build Coastguard Worker   else if (!(Val & 0x100))
3744*9880d681SAndroid Build Coastguard Worker     imm *= -1;
3745*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3746*9880d681SAndroid Build Coastguard Worker 
3747*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3748*9880d681SAndroid Build Coastguard Worker }
3749*9880d681SAndroid Build Coastguard Worker 
3750*9880d681SAndroid Build Coastguard Worker 
DecodeT2AddrModeImm8(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3751*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeImm8(MCInst &Inst, unsigned Val,
3752*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
3753*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3754*9880d681SAndroid Build Coastguard Worker 
3755*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 9, 4);
3756*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 0, 9);
3757*9880d681SAndroid Build Coastguard Worker 
3758*9880d681SAndroid Build Coastguard Worker   // Thumb stores cannot use PC as dest register.
3759*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
3760*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRT:
3761*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRBT:
3762*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRHT:
3763*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRi8:
3764*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRHi8:
3765*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRBi8:
3766*9880d681SAndroid Build Coastguard Worker     if (Rn == 15)
3767*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3768*9880d681SAndroid Build Coastguard Worker     break;
3769*9880d681SAndroid Build Coastguard Worker   default:
3770*9880d681SAndroid Build Coastguard Worker     break;
3771*9880d681SAndroid Build Coastguard Worker   }
3772*9880d681SAndroid Build Coastguard Worker 
3773*9880d681SAndroid Build Coastguard Worker   // Some instructions always use an additive offset.
3774*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
3775*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRT:
3776*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRBT:
3777*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRHT:
3778*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSBT:
3779*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSHT:
3780*9880d681SAndroid Build Coastguard Worker     case ARM::t2STRT:
3781*9880d681SAndroid Build Coastguard Worker     case ARM::t2STRBT:
3782*9880d681SAndroid Build Coastguard Worker     case ARM::t2STRHT:
3783*9880d681SAndroid Build Coastguard Worker       imm |= 0x100;
3784*9880d681SAndroid Build Coastguard Worker       break;
3785*9880d681SAndroid Build Coastguard Worker     default:
3786*9880d681SAndroid Build Coastguard Worker       break;
3787*9880d681SAndroid Build Coastguard Worker   }
3788*9880d681SAndroid Build Coastguard Worker 
3789*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3790*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3791*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2Imm8(Inst, imm, Address, Decoder)))
3792*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3793*9880d681SAndroid Build Coastguard Worker 
3794*9880d681SAndroid Build Coastguard Worker   return S;
3795*9880d681SAndroid Build Coastguard Worker }
3796*9880d681SAndroid Build Coastguard Worker 
DecodeT2LdStPre(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3797*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2LdStPre(MCInst &Inst, unsigned Insn,
3798*9880d681SAndroid Build Coastguard Worker                                     uint64_t Address, const void *Decoder) {
3799*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3800*9880d681SAndroid Build Coastguard Worker 
3801*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
3802*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
3803*9880d681SAndroid Build Coastguard Worker   unsigned addr = fieldFromInstruction(Insn, 0, 8);
3804*9880d681SAndroid Build Coastguard Worker   addr |= fieldFromInstruction(Insn, 9, 1) << 8;
3805*9880d681SAndroid Build Coastguard Worker   addr |= Rn << 9;
3806*9880d681SAndroid Build Coastguard Worker   unsigned load = fieldFromInstruction(Insn, 20, 1);
3807*9880d681SAndroid Build Coastguard Worker 
3808*9880d681SAndroid Build Coastguard Worker   if (Rn == 15) {
3809*9880d681SAndroid Build Coastguard Worker     switch (Inst.getOpcode()) {
3810*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDR_PRE:
3811*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDR_POST:
3812*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRpci);
3813*9880d681SAndroid Build Coastguard Worker       break;
3814*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRB_PRE:
3815*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRB_POST:
3816*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRBpci);
3817*9880d681SAndroid Build Coastguard Worker       break;
3818*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRH_PRE:
3819*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRH_POST:
3820*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRHpci);
3821*9880d681SAndroid Build Coastguard Worker       break;
3822*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSB_PRE:
3823*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSB_POST:
3824*9880d681SAndroid Build Coastguard Worker       if (Rt == 15)
3825*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::t2PLIpci);
3826*9880d681SAndroid Build Coastguard Worker       else
3827*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::t2LDRSBpci);
3828*9880d681SAndroid Build Coastguard Worker       break;
3829*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSH_PRE:
3830*9880d681SAndroid Build Coastguard Worker     case ARM::t2LDRSH_POST:
3831*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::t2LDRSHpci);
3832*9880d681SAndroid Build Coastguard Worker       break;
3833*9880d681SAndroid Build Coastguard Worker     default:
3834*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3835*9880d681SAndroid Build Coastguard Worker     }
3836*9880d681SAndroid Build Coastguard Worker     return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
3837*9880d681SAndroid Build Coastguard Worker   }
3838*9880d681SAndroid Build Coastguard Worker 
3839*9880d681SAndroid Build Coastguard Worker   if (!load) {
3840*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3841*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3842*9880d681SAndroid Build Coastguard Worker   }
3843*9880d681SAndroid Build Coastguard Worker 
3844*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
3845*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3846*9880d681SAndroid Build Coastguard Worker 
3847*9880d681SAndroid Build Coastguard Worker   if (load) {
3848*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3849*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3850*9880d681SAndroid Build Coastguard Worker   }
3851*9880d681SAndroid Build Coastguard Worker 
3852*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2AddrModeImm8(Inst, addr, Address, Decoder)))
3853*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3854*9880d681SAndroid Build Coastguard Worker 
3855*9880d681SAndroid Build Coastguard Worker   return S;
3856*9880d681SAndroid Build Coastguard Worker }
3857*9880d681SAndroid Build Coastguard Worker 
DecodeT2AddrModeImm12(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3858*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2AddrModeImm12(MCInst &Inst, unsigned Val,
3859*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
3860*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3861*9880d681SAndroid Build Coastguard Worker 
3862*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 13, 4);
3863*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Val, 0, 12);
3864*9880d681SAndroid Build Coastguard Worker 
3865*9880d681SAndroid Build Coastguard Worker   // Thumb stores cannot use PC as dest register.
3866*9880d681SAndroid Build Coastguard Worker   switch (Inst.getOpcode()) {
3867*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRi12:
3868*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRBi12:
3869*9880d681SAndroid Build Coastguard Worker   case ARM::t2STRHi12:
3870*9880d681SAndroid Build Coastguard Worker     if (Rn == 15)
3871*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
3872*9880d681SAndroid Build Coastguard Worker   default:
3873*9880d681SAndroid Build Coastguard Worker     break;
3874*9880d681SAndroid Build Coastguard Worker   }
3875*9880d681SAndroid Build Coastguard Worker 
3876*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3877*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3878*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3879*9880d681SAndroid Build Coastguard Worker 
3880*9880d681SAndroid Build Coastguard Worker   return S;
3881*9880d681SAndroid Build Coastguard Worker }
3882*9880d681SAndroid Build Coastguard Worker 
3883*9880d681SAndroid Build Coastguard Worker 
DecodeThumbAddSPImm(MCInst & Inst,uint16_t Insn,uint64_t Address,const void * Decoder)3884*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddSPImm(MCInst &Inst, uint16_t Insn,
3885*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder) {
3886*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 7);
3887*9880d681SAndroid Build Coastguard Worker 
3888*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(ARM::SP));
3889*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(ARM::SP));
3890*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imm));
3891*9880d681SAndroid Build Coastguard Worker 
3892*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3893*9880d681SAndroid Build Coastguard Worker }
3894*9880d681SAndroid Build Coastguard Worker 
DecodeThumbAddSPReg(MCInst & Inst,uint16_t Insn,uint64_t Address,const void * Decoder)3895*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbAddSPReg(MCInst &Inst, uint16_t Insn,
3896*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder) {
3897*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3898*9880d681SAndroid Build Coastguard Worker 
3899*9880d681SAndroid Build Coastguard Worker   if (Inst.getOpcode() == ARM::tADDrSP) {
3900*9880d681SAndroid Build Coastguard Worker     unsigned Rdm = fieldFromInstruction(Insn, 0, 3);
3901*9880d681SAndroid Build Coastguard Worker     Rdm |= fieldFromInstruction(Insn, 7, 1) << 3;
3902*9880d681SAndroid Build Coastguard Worker 
3903*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder)))
3904*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3905*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(ARM::SP));
3906*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder)))
3907*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3908*9880d681SAndroid Build Coastguard Worker   } else if (Inst.getOpcode() == ARM::tADDspr) {
3909*9880d681SAndroid Build Coastguard Worker     unsigned Rm = fieldFromInstruction(Insn, 3, 4);
3910*9880d681SAndroid Build Coastguard Worker 
3911*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(ARM::SP));
3912*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(ARM::SP));
3913*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
3914*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3915*9880d681SAndroid Build Coastguard Worker   }
3916*9880d681SAndroid Build Coastguard Worker 
3917*9880d681SAndroid Build Coastguard Worker   return S;
3918*9880d681SAndroid Build Coastguard Worker }
3919*9880d681SAndroid Build Coastguard Worker 
DecodeThumbCPS(MCInst & Inst,uint16_t Insn,uint64_t Address,const void * Decoder)3920*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbCPS(MCInst &Inst, uint16_t Insn,
3921*9880d681SAndroid Build Coastguard Worker                            uint64_t Address, const void *Decoder) {
3922*9880d681SAndroid Build Coastguard Worker   unsigned imod = fieldFromInstruction(Insn, 4, 1) | 0x2;
3923*9880d681SAndroid Build Coastguard Worker   unsigned flags = fieldFromInstruction(Insn, 0, 3);
3924*9880d681SAndroid Build Coastguard Worker 
3925*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(imod));
3926*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(flags));
3927*9880d681SAndroid Build Coastguard Worker 
3928*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3929*9880d681SAndroid Build Coastguard Worker }
3930*9880d681SAndroid Build Coastguard Worker 
DecodePostIdxReg(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3931*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodePostIdxReg(MCInst &Inst, unsigned Insn,
3932*9880d681SAndroid Build Coastguard Worker                              uint64_t Address, const void *Decoder) {
3933*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3934*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
3935*9880d681SAndroid Build Coastguard Worker   unsigned add = fieldFromInstruction(Insn, 4, 1);
3936*9880d681SAndroid Build Coastguard Worker 
3937*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)))
3938*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3939*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(add));
3940*9880d681SAndroid Build Coastguard Worker 
3941*9880d681SAndroid Build Coastguard Worker   return S;
3942*9880d681SAndroid Build Coastguard Worker }
3943*9880d681SAndroid Build Coastguard Worker 
DecodeThumbBLXOffset(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3944*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbBLXOffset(MCInst &Inst, unsigned Val,
3945*9880d681SAndroid Build Coastguard Worker                                  uint64_t Address, const void *Decoder) {
3946*9880d681SAndroid Build Coastguard Worker   // Val is passed in as S:J1:J2:imm10H:imm10L:'0'
3947*9880d681SAndroid Build Coastguard Worker   // Note only one trailing zero not two.  Also the J1 and J2 values are from
3948*9880d681SAndroid Build Coastguard Worker   // the encoded instruction.  So here change to I1 and I2 values via:
3949*9880d681SAndroid Build Coastguard Worker   // I1 = NOT(J1 EOR S);
3950*9880d681SAndroid Build Coastguard Worker   // I2 = NOT(J2 EOR S);
3951*9880d681SAndroid Build Coastguard Worker   // and build the imm32 with two trailing zeros as documented:
3952*9880d681SAndroid Build Coastguard Worker   // imm32 = SignExtend(S:I1:I2:imm10H:imm10L:'00', 32);
3953*9880d681SAndroid Build Coastguard Worker   unsigned S = (Val >> 23) & 1;
3954*9880d681SAndroid Build Coastguard Worker   unsigned J1 = (Val >> 22) & 1;
3955*9880d681SAndroid Build Coastguard Worker   unsigned J2 = (Val >> 21) & 1;
3956*9880d681SAndroid Build Coastguard Worker   unsigned I1 = !(J1 ^ S);
3957*9880d681SAndroid Build Coastguard Worker   unsigned I2 = !(J2 ^ S);
3958*9880d681SAndroid Build Coastguard Worker   unsigned tmp = (Val & ~0x600000) | (I1 << 22) | (I2 << 21);
3959*9880d681SAndroid Build Coastguard Worker   int imm32 = SignExtend32<25>(tmp << 1);
3960*9880d681SAndroid Build Coastguard Worker 
3961*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address,
3962*9880d681SAndroid Build Coastguard Worker                                 (Address & ~2u) + imm32 + 4,
3963*9880d681SAndroid Build Coastguard Worker                                 true, 4, Inst, Decoder))
3964*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imm32));
3965*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3966*9880d681SAndroid Build Coastguard Worker }
3967*9880d681SAndroid Build Coastguard Worker 
DecodeCoprocessor(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)3968*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeCoprocessor(MCInst &Inst, unsigned Val,
3969*9880d681SAndroid Build Coastguard Worker                               uint64_t Address, const void *Decoder) {
3970*9880d681SAndroid Build Coastguard Worker   if (Val == 0xA || Val == 0xB)
3971*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3972*9880d681SAndroid Build Coastguard Worker 
3973*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
3974*9880d681SAndroid Build Coastguard Worker     ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
3975*9880d681SAndroid Build Coastguard Worker 
3976*9880d681SAndroid Build Coastguard Worker   if (featureBits[ARM::HasV8Ops] && !(Val == 14 || Val == 15))
3977*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3978*9880d681SAndroid Build Coastguard Worker 
3979*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Val));
3980*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
3981*9880d681SAndroid Build Coastguard Worker }
3982*9880d681SAndroid Build Coastguard Worker 
3983*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeThumbTableBranch(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)3984*9880d681SAndroid Build Coastguard Worker DecodeThumbTableBranch(MCInst &Inst, unsigned Insn,
3985*9880d681SAndroid Build Coastguard Worker                        uint64_t Address, const void *Decoder) {
3986*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
3987*9880d681SAndroid Build Coastguard Worker 
3988*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
3989*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
3990*9880d681SAndroid Build Coastguard Worker 
3991*9880d681SAndroid Build Coastguard Worker   if (Rn == ARM::SP) S = MCDisassembler::SoftFail;
3992*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
3993*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3994*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
3995*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
3996*9880d681SAndroid Build Coastguard Worker   return S;
3997*9880d681SAndroid Build Coastguard Worker }
3998*9880d681SAndroid Build Coastguard Worker 
3999*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeThumb2BCCInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4000*9880d681SAndroid Build Coastguard Worker DecodeThumb2BCCInstruction(MCInst &Inst, unsigned Insn,
4001*9880d681SAndroid Build Coastguard Worker                            uint64_t Address, const void *Decoder) {
4002*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4003*9880d681SAndroid Build Coastguard Worker 
4004*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 22, 4);
4005*9880d681SAndroid Build Coastguard Worker   if (pred == 0xE || pred == 0xF) {
4006*9880d681SAndroid Build Coastguard Worker     unsigned opc = fieldFromInstruction(Insn, 4, 28);
4007*9880d681SAndroid Build Coastguard Worker     switch (opc) {
4008*9880d681SAndroid Build Coastguard Worker       default:
4009*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
4010*9880d681SAndroid Build Coastguard Worker       case 0xf3bf8f4:
4011*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::t2DSB);
4012*9880d681SAndroid Build Coastguard Worker         break;
4013*9880d681SAndroid Build Coastguard Worker       case 0xf3bf8f5:
4014*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::t2DMB);
4015*9880d681SAndroid Build Coastguard Worker         break;
4016*9880d681SAndroid Build Coastguard Worker       case 0xf3bf8f6:
4017*9880d681SAndroid Build Coastguard Worker         Inst.setOpcode(ARM::t2ISB);
4018*9880d681SAndroid Build Coastguard Worker         break;
4019*9880d681SAndroid Build Coastguard Worker     }
4020*9880d681SAndroid Build Coastguard Worker 
4021*9880d681SAndroid Build Coastguard Worker     unsigned imm = fieldFromInstruction(Insn, 0, 4);
4022*9880d681SAndroid Build Coastguard Worker     return DecodeMemBarrierOption(Inst, imm, Address, Decoder);
4023*9880d681SAndroid Build Coastguard Worker   }
4024*9880d681SAndroid Build Coastguard Worker 
4025*9880d681SAndroid Build Coastguard Worker   unsigned brtarget = fieldFromInstruction(Insn, 0, 11) << 1;
4026*9880d681SAndroid Build Coastguard Worker   brtarget |= fieldFromInstruction(Insn, 11, 1) << 19;
4027*9880d681SAndroid Build Coastguard Worker   brtarget |= fieldFromInstruction(Insn, 13, 1) << 18;
4028*9880d681SAndroid Build Coastguard Worker   brtarget |= fieldFromInstruction(Insn, 16, 6) << 12;
4029*9880d681SAndroid Build Coastguard Worker   brtarget |= fieldFromInstruction(Insn, 26, 1) << 20;
4030*9880d681SAndroid Build Coastguard Worker 
4031*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2BROperand(Inst, brtarget, Address, Decoder)))
4032*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4033*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
4034*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4035*9880d681SAndroid Build Coastguard Worker 
4036*9880d681SAndroid Build Coastguard Worker   return S;
4037*9880d681SAndroid Build Coastguard Worker }
4038*9880d681SAndroid Build Coastguard Worker 
4039*9880d681SAndroid Build Coastguard Worker // Decode a shifted immediate operand.  These basically consist
4040*9880d681SAndroid Build Coastguard Worker // of an 8-bit value, and a 4-bit directive that specifies either
4041*9880d681SAndroid Build Coastguard Worker // a splat operation or a rotation.
DecodeT2SOImm(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)4042*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2SOImm(MCInst &Inst, unsigned Val,
4043*9880d681SAndroid Build Coastguard Worker                           uint64_t Address, const void *Decoder) {
4044*9880d681SAndroid Build Coastguard Worker   unsigned ctrl = fieldFromInstruction(Val, 10, 2);
4045*9880d681SAndroid Build Coastguard Worker   if (ctrl == 0) {
4046*9880d681SAndroid Build Coastguard Worker     unsigned byte = fieldFromInstruction(Val, 8, 2);
4047*9880d681SAndroid Build Coastguard Worker     unsigned imm = fieldFromInstruction(Val, 0, 8);
4048*9880d681SAndroid Build Coastguard Worker     switch (byte) {
4049*9880d681SAndroid Build Coastguard Worker       case 0:
4050*9880d681SAndroid Build Coastguard Worker         Inst.addOperand(MCOperand::createImm(imm));
4051*9880d681SAndroid Build Coastguard Worker         break;
4052*9880d681SAndroid Build Coastguard Worker       case 1:
4053*9880d681SAndroid Build Coastguard Worker         Inst.addOperand(MCOperand::createImm((imm << 16) | imm));
4054*9880d681SAndroid Build Coastguard Worker         break;
4055*9880d681SAndroid Build Coastguard Worker       case 2:
4056*9880d681SAndroid Build Coastguard Worker         Inst.addOperand(MCOperand::createImm((imm << 24) | (imm << 8)));
4057*9880d681SAndroid Build Coastguard Worker         break;
4058*9880d681SAndroid Build Coastguard Worker       case 3:
4059*9880d681SAndroid Build Coastguard Worker         Inst.addOperand(MCOperand::createImm((imm << 24) | (imm << 16) |
4060*9880d681SAndroid Build Coastguard Worker                                              (imm << 8)  |  imm));
4061*9880d681SAndroid Build Coastguard Worker         break;
4062*9880d681SAndroid Build Coastguard Worker     }
4063*9880d681SAndroid Build Coastguard Worker   } else {
4064*9880d681SAndroid Build Coastguard Worker     unsigned unrot = fieldFromInstruction(Val, 0, 7) | 0x80;
4065*9880d681SAndroid Build Coastguard Worker     unsigned rot = fieldFromInstruction(Val, 7, 5);
4066*9880d681SAndroid Build Coastguard Worker     unsigned imm = (unrot >> rot) | (unrot << ((32-rot)&31));
4067*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imm));
4068*9880d681SAndroid Build Coastguard Worker   }
4069*9880d681SAndroid Build Coastguard Worker 
4070*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
4071*9880d681SAndroid Build Coastguard Worker }
4072*9880d681SAndroid Build Coastguard Worker 
4073*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeThumbBCCTargetOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)4074*9880d681SAndroid Build Coastguard Worker DecodeThumbBCCTargetOperand(MCInst &Inst, unsigned Val,
4075*9880d681SAndroid Build Coastguard Worker                             uint64_t Address, const void *Decoder){
4076*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<9>(Val<<1) + 4,
4077*9880d681SAndroid Build Coastguard Worker                                 true, 2, Inst, Decoder))
4078*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(SignExtend32<9>(Val << 1)));
4079*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
4080*9880d681SAndroid Build Coastguard Worker }
4081*9880d681SAndroid Build Coastguard Worker 
DecodeThumbBLTargetOperand(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)4082*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeThumbBLTargetOperand(MCInst &Inst, unsigned Val,
4083*9880d681SAndroid Build Coastguard Worker                                        uint64_t Address, const void *Decoder){
4084*9880d681SAndroid Build Coastguard Worker   // Val is passed in as S:J1:J2:imm10:imm11
4085*9880d681SAndroid Build Coastguard Worker   // Note no trailing zero after imm11.  Also the J1 and J2 values are from
4086*9880d681SAndroid Build Coastguard Worker   // the encoded instruction.  So here change to I1 and I2 values via:
4087*9880d681SAndroid Build Coastguard Worker   // I1 = NOT(J1 EOR S);
4088*9880d681SAndroid Build Coastguard Worker   // I2 = NOT(J2 EOR S);
4089*9880d681SAndroid Build Coastguard Worker   // and build the imm32 with one trailing zero as documented:
4090*9880d681SAndroid Build Coastguard Worker   // imm32 = SignExtend(S:I1:I2:imm10:imm11:'0', 32);
4091*9880d681SAndroid Build Coastguard Worker   unsigned S = (Val >> 23) & 1;
4092*9880d681SAndroid Build Coastguard Worker   unsigned J1 = (Val >> 22) & 1;
4093*9880d681SAndroid Build Coastguard Worker   unsigned J2 = (Val >> 21) & 1;
4094*9880d681SAndroid Build Coastguard Worker   unsigned I1 = !(J1 ^ S);
4095*9880d681SAndroid Build Coastguard Worker   unsigned I2 = !(J2 ^ S);
4096*9880d681SAndroid Build Coastguard Worker   unsigned tmp = (Val & ~0x600000) | (I1 << 22) | (I2 << 21);
4097*9880d681SAndroid Build Coastguard Worker   int imm32 = SignExtend32<25>(tmp << 1);
4098*9880d681SAndroid Build Coastguard Worker 
4099*9880d681SAndroid Build Coastguard Worker   if (!tryAddingSymbolicOperand(Address, Address + imm32 + 4,
4100*9880d681SAndroid Build Coastguard Worker                                 true, 4, Inst, Decoder))
4101*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(imm32));
4102*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
4103*9880d681SAndroid Build Coastguard Worker }
4104*9880d681SAndroid Build Coastguard Worker 
DecodeMemBarrierOption(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)4105*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeMemBarrierOption(MCInst &Inst, unsigned Val,
4106*9880d681SAndroid Build Coastguard Worker                                    uint64_t Address, const void *Decoder) {
4107*9880d681SAndroid Build Coastguard Worker   if (Val & ~0xf)
4108*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4109*9880d681SAndroid Build Coastguard Worker 
4110*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Val));
4111*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
4112*9880d681SAndroid Build Coastguard Worker }
4113*9880d681SAndroid Build Coastguard Worker 
DecodeInstSyncBarrierOption(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)4114*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeInstSyncBarrierOption(MCInst &Inst, unsigned Val,
4115*9880d681SAndroid Build Coastguard Worker                                         uint64_t Address, const void *Decoder) {
4116*9880d681SAndroid Build Coastguard Worker   if (Val & ~0xf)
4117*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4118*9880d681SAndroid Build Coastguard Worker 
4119*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Val));
4120*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
4121*9880d681SAndroid Build Coastguard Worker }
4122*9880d681SAndroid Build Coastguard Worker 
DecodeMSRMask(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)4123*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
4124*9880d681SAndroid Build Coastguard Worker                           uint64_t Address, const void *Decoder) {
4125*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4126*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &FeatureBits =
4127*9880d681SAndroid Build Coastguard Worker     ((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
4128*9880d681SAndroid Build Coastguard Worker 
4129*9880d681SAndroid Build Coastguard Worker   if (FeatureBits[ARM::FeatureMClass]) {
4130*9880d681SAndroid Build Coastguard Worker     unsigned ValLow = Val & 0xff;
4131*9880d681SAndroid Build Coastguard Worker 
4132*9880d681SAndroid Build Coastguard Worker     // Validate the SYSm value first.
4133*9880d681SAndroid Build Coastguard Worker     switch (ValLow) {
4134*9880d681SAndroid Build Coastguard Worker     case  0: // apsr
4135*9880d681SAndroid Build Coastguard Worker     case  1: // iapsr
4136*9880d681SAndroid Build Coastguard Worker     case  2: // eapsr
4137*9880d681SAndroid Build Coastguard Worker     case  3: // xpsr
4138*9880d681SAndroid Build Coastguard Worker     case  5: // ipsr
4139*9880d681SAndroid Build Coastguard Worker     case  6: // epsr
4140*9880d681SAndroid Build Coastguard Worker     case  7: // iepsr
4141*9880d681SAndroid Build Coastguard Worker     case  8: // msp
4142*9880d681SAndroid Build Coastguard Worker     case  9: // psp
4143*9880d681SAndroid Build Coastguard Worker     case 16: // primask
4144*9880d681SAndroid Build Coastguard Worker     case 20: // control
4145*9880d681SAndroid Build Coastguard Worker       break;
4146*9880d681SAndroid Build Coastguard Worker     case 17: // basepri
4147*9880d681SAndroid Build Coastguard Worker     case 18: // basepri_max
4148*9880d681SAndroid Build Coastguard Worker     case 19: // faultmask
4149*9880d681SAndroid Build Coastguard Worker       if (!(FeatureBits[ARM::HasV7Ops]))
4150*9880d681SAndroid Build Coastguard Worker         // Values basepri, basepri_max and faultmask are only valid for v7m.
4151*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
4152*9880d681SAndroid Build Coastguard Worker       break;
4153*9880d681SAndroid Build Coastguard Worker     case 0x8a: // msplim_ns
4154*9880d681SAndroid Build Coastguard Worker     case 0x8b: // psplim_ns
4155*9880d681SAndroid Build Coastguard Worker     case 0x91: // basepri_ns
4156*9880d681SAndroid Build Coastguard Worker     case 0x92: // basepri_max_ns
4157*9880d681SAndroid Build Coastguard Worker     case 0x93: // faultmask_ns
4158*9880d681SAndroid Build Coastguard Worker       if (!(FeatureBits[ARM::HasV8MMainlineOps]))
4159*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
4160*9880d681SAndroid Build Coastguard Worker       // fall through
4161*9880d681SAndroid Build Coastguard Worker     case 10:   // msplim
4162*9880d681SAndroid Build Coastguard Worker     case 11:   // psplim
4163*9880d681SAndroid Build Coastguard Worker     case 0x88: // msp_ns
4164*9880d681SAndroid Build Coastguard Worker     case 0x89: // psp_ns
4165*9880d681SAndroid Build Coastguard Worker     case 0x90: // primask_ns
4166*9880d681SAndroid Build Coastguard Worker     case 0x94: // control_ns
4167*9880d681SAndroid Build Coastguard Worker     case 0x98: // sp_ns
4168*9880d681SAndroid Build Coastguard Worker       if (!(FeatureBits[ARM::Feature8MSecExt]))
4169*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
4170*9880d681SAndroid Build Coastguard Worker       break;
4171*9880d681SAndroid Build Coastguard Worker     default:
4172*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4173*9880d681SAndroid Build Coastguard Worker     }
4174*9880d681SAndroid Build Coastguard Worker 
4175*9880d681SAndroid Build Coastguard Worker     if (Inst.getOpcode() == ARM::t2MSR_M) {
4176*9880d681SAndroid Build Coastguard Worker       unsigned Mask = fieldFromInstruction(Val, 10, 2);
4177*9880d681SAndroid Build Coastguard Worker       if (!(FeatureBits[ARM::HasV7Ops])) {
4178*9880d681SAndroid Build Coastguard Worker         // The ARMv6-M MSR bits {11-10} can be only 0b10, other values are
4179*9880d681SAndroid Build Coastguard Worker         // unpredictable.
4180*9880d681SAndroid Build Coastguard Worker         if (Mask != 2)
4181*9880d681SAndroid Build Coastguard Worker           S = MCDisassembler::SoftFail;
4182*9880d681SAndroid Build Coastguard Worker       }
4183*9880d681SAndroid Build Coastguard Worker       else {
4184*9880d681SAndroid Build Coastguard Worker         // The ARMv7-M architecture stores an additional 2-bit mask value in
4185*9880d681SAndroid Build Coastguard Worker         // MSR bits {11-10}. The mask is used only with apsr, iapsr, eapsr and
4186*9880d681SAndroid Build Coastguard Worker         // xpsr, it has to be 0b10 in other cases. Bit mask{1} indicates if
4187*9880d681SAndroid Build Coastguard Worker         // the NZCVQ bits should be moved by the instruction. Bit mask{0}
4188*9880d681SAndroid Build Coastguard Worker         // indicates the move for the GE{3:0} bits, the mask{0} bit can be set
4189*9880d681SAndroid Build Coastguard Worker         // only if the processor includes the DSP extension.
4190*9880d681SAndroid Build Coastguard Worker         if (Mask == 0 || (Mask != 2 && ValLow > 3) ||
4191*9880d681SAndroid Build Coastguard Worker             (!(FeatureBits[ARM::FeatureDSP]) && (Mask & 1)))
4192*9880d681SAndroid Build Coastguard Worker           S = MCDisassembler::SoftFail;
4193*9880d681SAndroid Build Coastguard Worker       }
4194*9880d681SAndroid Build Coastguard Worker     }
4195*9880d681SAndroid Build Coastguard Worker   } else {
4196*9880d681SAndroid Build Coastguard Worker     // A/R class
4197*9880d681SAndroid Build Coastguard Worker     if (Val == 0)
4198*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4199*9880d681SAndroid Build Coastguard Worker   }
4200*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Val));
4201*9880d681SAndroid Build Coastguard Worker   return S;
4202*9880d681SAndroid Build Coastguard Worker }
4203*9880d681SAndroid Build Coastguard Worker 
DecodeBankedReg(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)4204*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeBankedReg(MCInst &Inst, unsigned Val,
4205*9880d681SAndroid Build Coastguard Worker                                     uint64_t Address, const void *Decoder) {
4206*9880d681SAndroid Build Coastguard Worker 
4207*9880d681SAndroid Build Coastguard Worker   unsigned R = fieldFromInstruction(Val, 5, 1);
4208*9880d681SAndroid Build Coastguard Worker   unsigned SysM = fieldFromInstruction(Val, 0, 5);
4209*9880d681SAndroid Build Coastguard Worker 
4210*9880d681SAndroid Build Coastguard Worker   // The table of encodings for these banked registers comes from B9.2.3 of the
4211*9880d681SAndroid Build Coastguard Worker   // ARM ARM. There are patterns, but nothing regular enough to make this logic
4212*9880d681SAndroid Build Coastguard Worker   // neater. So by fiat, these values are UNPREDICTABLE:
4213*9880d681SAndroid Build Coastguard Worker   if (!R) {
4214*9880d681SAndroid Build Coastguard Worker     if (SysM == 0x7 || SysM == 0xf || SysM == 0x18 || SysM == 0x19 ||
4215*9880d681SAndroid Build Coastguard Worker         SysM == 0x1a || SysM == 0x1b)
4216*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::SoftFail;
4217*9880d681SAndroid Build Coastguard Worker   } else {
4218*9880d681SAndroid Build Coastguard Worker     if (SysM != 0xe && SysM != 0x10 && SysM != 0x12 && SysM != 0x14 &&
4219*9880d681SAndroid Build Coastguard Worker         SysM != 0x16 && SysM != 0x1c && SysM != 0x1e)
4220*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::SoftFail;
4221*9880d681SAndroid Build Coastguard Worker   }
4222*9880d681SAndroid Build Coastguard Worker 
4223*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Val));
4224*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
4225*9880d681SAndroid Build Coastguard Worker }
4226*9880d681SAndroid Build Coastguard Worker 
DecodeDoubleRegLoad(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4227*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDoubleRegLoad(MCInst &Inst, unsigned Insn,
4228*9880d681SAndroid Build Coastguard Worker                                         uint64_t Address, const void *Decoder) {
4229*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4230*9880d681SAndroid Build Coastguard Worker 
4231*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
4232*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4233*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
4234*9880d681SAndroid Build Coastguard Worker 
4235*9880d681SAndroid Build Coastguard Worker   if (Rn == 0xF)
4236*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
4237*9880d681SAndroid Build Coastguard Worker 
4238*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRPairRegisterClass(Inst, Rt, Address, Decoder)))
4239*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4240*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4241*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4242*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
4243*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4244*9880d681SAndroid Build Coastguard Worker 
4245*9880d681SAndroid Build Coastguard Worker   return S;
4246*9880d681SAndroid Build Coastguard Worker }
4247*9880d681SAndroid Build Coastguard Worker 
DecodeDoubleRegStore(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4248*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeDoubleRegStore(MCInst &Inst, unsigned Insn,
4249*9880d681SAndroid Build Coastguard Worker                                          uint64_t Address, const void *Decoder){
4250*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4251*9880d681SAndroid Build Coastguard Worker 
4252*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
4253*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 0, 4);
4254*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4255*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
4256*9880d681SAndroid Build Coastguard Worker 
4257*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder)))
4258*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4259*9880d681SAndroid Build Coastguard Worker 
4260*9880d681SAndroid Build Coastguard Worker   if (Rn == 0xF || Rd == Rn || Rd == Rt || Rd == Rt+1)
4261*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
4262*9880d681SAndroid Build Coastguard Worker 
4263*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRPairRegisterClass(Inst, Rt, Address, Decoder)))
4264*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4265*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4266*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4267*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
4268*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4269*9880d681SAndroid Build Coastguard Worker 
4270*9880d681SAndroid Build Coastguard Worker   return S;
4271*9880d681SAndroid Build Coastguard Worker }
4272*9880d681SAndroid Build Coastguard Worker 
DecodeLDRPreImm(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4273*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeLDRPreImm(MCInst &Inst, unsigned Insn,
4274*9880d681SAndroid Build Coastguard Worker                             uint64_t Address, const void *Decoder) {
4275*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4276*9880d681SAndroid Build Coastguard Worker 
4277*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4278*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
4279*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 12);
4280*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 16, 4) << 13;
4281*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 23, 1) << 12;
4282*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
4283*9880d681SAndroid Build Coastguard Worker 
4284*9880d681SAndroid Build Coastguard Worker   if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail;
4285*9880d681SAndroid Build Coastguard Worker 
4286*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
4287*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4288*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4289*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4290*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeAddrModeImm12Operand(Inst, imm, Address, Decoder)))
4291*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4292*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
4293*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4294*9880d681SAndroid Build Coastguard Worker 
4295*9880d681SAndroid Build Coastguard Worker   return S;
4296*9880d681SAndroid Build Coastguard Worker }
4297*9880d681SAndroid Build Coastguard Worker 
DecodeLDRPreReg(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4298*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeLDRPreReg(MCInst &Inst, unsigned Insn,
4299*9880d681SAndroid Build Coastguard Worker                             uint64_t Address, const void *Decoder) {
4300*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4301*9880d681SAndroid Build Coastguard Worker 
4302*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4303*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
4304*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 12);
4305*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 16, 4) << 13;
4306*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 23, 1) << 12;
4307*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
4308*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
4309*9880d681SAndroid Build Coastguard Worker 
4310*9880d681SAndroid Build Coastguard Worker   if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail;
4311*9880d681SAndroid Build Coastguard Worker   if (Rm == 0xF) S = MCDisassembler::SoftFail;
4312*9880d681SAndroid Build Coastguard Worker 
4313*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
4314*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4315*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4316*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4317*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeSORegMemOperand(Inst, imm, Address, Decoder)))
4318*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4319*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
4320*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4321*9880d681SAndroid Build Coastguard Worker 
4322*9880d681SAndroid Build Coastguard Worker   return S;
4323*9880d681SAndroid Build Coastguard Worker }
4324*9880d681SAndroid Build Coastguard Worker 
4325*9880d681SAndroid Build Coastguard Worker 
DecodeSTRPreImm(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4326*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSTRPreImm(MCInst &Inst, unsigned Insn,
4327*9880d681SAndroid Build Coastguard Worker                             uint64_t Address, const void *Decoder) {
4328*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4329*9880d681SAndroid Build Coastguard Worker 
4330*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4331*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
4332*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 12);
4333*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 16, 4) << 13;
4334*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 23, 1) << 12;
4335*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
4336*9880d681SAndroid Build Coastguard Worker 
4337*9880d681SAndroid Build Coastguard Worker   if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail;
4338*9880d681SAndroid Build Coastguard Worker 
4339*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4340*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4341*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
4342*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4343*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeAddrModeImm12Operand(Inst, imm, Address, Decoder)))
4344*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4345*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
4346*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4347*9880d681SAndroid Build Coastguard Worker 
4348*9880d681SAndroid Build Coastguard Worker   return S;
4349*9880d681SAndroid Build Coastguard Worker }
4350*9880d681SAndroid Build Coastguard Worker 
DecodeSTRPreReg(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4351*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSTRPreReg(MCInst &Inst, unsigned Insn,
4352*9880d681SAndroid Build Coastguard Worker                             uint64_t Address, const void *Decoder) {
4353*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4354*9880d681SAndroid Build Coastguard Worker 
4355*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4356*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
4357*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 0, 12);
4358*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 16, 4) << 13;
4359*9880d681SAndroid Build Coastguard Worker   imm |= fieldFromInstruction(Insn, 23, 1) << 12;
4360*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
4361*9880d681SAndroid Build Coastguard Worker 
4362*9880d681SAndroid Build Coastguard Worker   if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail;
4363*9880d681SAndroid Build Coastguard Worker 
4364*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4365*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4366*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
4367*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4368*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeSORegMemOperand(Inst, imm, Address, Decoder)))
4369*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4370*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
4371*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4372*9880d681SAndroid Build Coastguard Worker 
4373*9880d681SAndroid Build Coastguard Worker   return S;
4374*9880d681SAndroid Build Coastguard Worker }
4375*9880d681SAndroid Build Coastguard Worker 
DecodeVLD1LN(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4376*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD1LN(MCInst &Inst, unsigned Insn,
4377*9880d681SAndroid Build Coastguard Worker                          uint64_t Address, const void *Decoder) {
4378*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4379*9880d681SAndroid Build Coastguard Worker 
4380*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4381*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
4382*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
4383*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
4384*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 10, 2);
4385*9880d681SAndroid Build Coastguard Worker 
4386*9880d681SAndroid Build Coastguard Worker   unsigned align = 0;
4387*9880d681SAndroid Build Coastguard Worker   unsigned index = 0;
4388*9880d681SAndroid Build Coastguard Worker   switch (size) {
4389*9880d681SAndroid Build Coastguard Worker     default:
4390*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4391*9880d681SAndroid Build Coastguard Worker     case 0:
4392*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4393*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4394*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 5, 3);
4395*9880d681SAndroid Build Coastguard Worker       break;
4396*9880d681SAndroid Build Coastguard Worker     case 1:
4397*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4398*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4399*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 6, 2);
4400*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4401*9880d681SAndroid Build Coastguard Worker         align = 2;
4402*9880d681SAndroid Build Coastguard Worker       break;
4403*9880d681SAndroid Build Coastguard Worker     case 2:
4404*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 6, 1))
4405*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4406*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 7, 1);
4407*9880d681SAndroid Build Coastguard Worker 
4408*9880d681SAndroid Build Coastguard Worker       switch (fieldFromInstruction(Insn, 4, 2)) {
4409*9880d681SAndroid Build Coastguard Worker         case 0 :
4410*9880d681SAndroid Build Coastguard Worker           align = 0; break;
4411*9880d681SAndroid Build Coastguard Worker         case 3:
4412*9880d681SAndroid Build Coastguard Worker           align = 4; break;
4413*9880d681SAndroid Build Coastguard Worker         default:
4414*9880d681SAndroid Build Coastguard Worker           return MCDisassembler::Fail;
4415*9880d681SAndroid Build Coastguard Worker       }
4416*9880d681SAndroid Build Coastguard Worker       break;
4417*9880d681SAndroid Build Coastguard Worker   }
4418*9880d681SAndroid Build Coastguard Worker 
4419*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4420*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4421*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) { // Writeback
4422*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4423*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4424*9880d681SAndroid Build Coastguard Worker   }
4425*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4426*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4427*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
4428*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
4429*9880d681SAndroid Build Coastguard Worker     if (Rm != 0xD) {
4430*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
4431*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
4432*9880d681SAndroid Build Coastguard Worker     } else
4433*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(0));
4434*9880d681SAndroid Build Coastguard Worker   }
4435*9880d681SAndroid Build Coastguard Worker 
4436*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4437*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4438*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(index));
4439*9880d681SAndroid Build Coastguard Worker 
4440*9880d681SAndroid Build Coastguard Worker   return S;
4441*9880d681SAndroid Build Coastguard Worker }
4442*9880d681SAndroid Build Coastguard Worker 
DecodeVST1LN(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4443*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVST1LN(MCInst &Inst, unsigned Insn,
4444*9880d681SAndroid Build Coastguard Worker                          uint64_t Address, const void *Decoder) {
4445*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4446*9880d681SAndroid Build Coastguard Worker 
4447*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4448*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
4449*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
4450*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
4451*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 10, 2);
4452*9880d681SAndroid Build Coastguard Worker 
4453*9880d681SAndroid Build Coastguard Worker   unsigned align = 0;
4454*9880d681SAndroid Build Coastguard Worker   unsigned index = 0;
4455*9880d681SAndroid Build Coastguard Worker   switch (size) {
4456*9880d681SAndroid Build Coastguard Worker     default:
4457*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4458*9880d681SAndroid Build Coastguard Worker     case 0:
4459*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4460*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4461*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 5, 3);
4462*9880d681SAndroid Build Coastguard Worker       break;
4463*9880d681SAndroid Build Coastguard Worker     case 1:
4464*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4465*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4466*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 6, 2);
4467*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4468*9880d681SAndroid Build Coastguard Worker         align = 2;
4469*9880d681SAndroid Build Coastguard Worker       break;
4470*9880d681SAndroid Build Coastguard Worker     case 2:
4471*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 6, 1))
4472*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4473*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 7, 1);
4474*9880d681SAndroid Build Coastguard Worker 
4475*9880d681SAndroid Build Coastguard Worker       switch (fieldFromInstruction(Insn, 4, 2)) {
4476*9880d681SAndroid Build Coastguard Worker         case 0:
4477*9880d681SAndroid Build Coastguard Worker           align = 0; break;
4478*9880d681SAndroid Build Coastguard Worker         case 3:
4479*9880d681SAndroid Build Coastguard Worker           align = 4; break;
4480*9880d681SAndroid Build Coastguard Worker         default:
4481*9880d681SAndroid Build Coastguard Worker           return MCDisassembler::Fail;
4482*9880d681SAndroid Build Coastguard Worker       }
4483*9880d681SAndroid Build Coastguard Worker       break;
4484*9880d681SAndroid Build Coastguard Worker   }
4485*9880d681SAndroid Build Coastguard Worker 
4486*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) { // Writeback
4487*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4488*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4489*9880d681SAndroid Build Coastguard Worker   }
4490*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4491*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4492*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
4493*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
4494*9880d681SAndroid Build Coastguard Worker     if (Rm != 0xD) {
4495*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
4496*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4497*9880d681SAndroid Build Coastguard Worker     } else
4498*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(0));
4499*9880d681SAndroid Build Coastguard Worker   }
4500*9880d681SAndroid Build Coastguard Worker 
4501*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4502*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4503*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(index));
4504*9880d681SAndroid Build Coastguard Worker 
4505*9880d681SAndroid Build Coastguard Worker   return S;
4506*9880d681SAndroid Build Coastguard Worker }
4507*9880d681SAndroid Build Coastguard Worker 
4508*9880d681SAndroid Build Coastguard Worker 
DecodeVLD2LN(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4509*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD2LN(MCInst &Inst, unsigned Insn,
4510*9880d681SAndroid Build Coastguard Worker                          uint64_t Address, const void *Decoder) {
4511*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4512*9880d681SAndroid Build Coastguard Worker 
4513*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4514*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
4515*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
4516*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
4517*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 10, 2);
4518*9880d681SAndroid Build Coastguard Worker 
4519*9880d681SAndroid Build Coastguard Worker   unsigned align = 0;
4520*9880d681SAndroid Build Coastguard Worker   unsigned index = 0;
4521*9880d681SAndroid Build Coastguard Worker   unsigned inc = 1;
4522*9880d681SAndroid Build Coastguard Worker   switch (size) {
4523*9880d681SAndroid Build Coastguard Worker     default:
4524*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4525*9880d681SAndroid Build Coastguard Worker     case 0:
4526*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 5, 3);
4527*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4528*9880d681SAndroid Build Coastguard Worker         align = 2;
4529*9880d681SAndroid Build Coastguard Worker       break;
4530*9880d681SAndroid Build Coastguard Worker     case 1:
4531*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 6, 2);
4532*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4533*9880d681SAndroid Build Coastguard Worker         align = 4;
4534*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4535*9880d681SAndroid Build Coastguard Worker         inc = 2;
4536*9880d681SAndroid Build Coastguard Worker       break;
4537*9880d681SAndroid Build Coastguard Worker     case 2:
4538*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4539*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4540*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 7, 1);
4541*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1) != 0)
4542*9880d681SAndroid Build Coastguard Worker         align = 8;
4543*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 6, 1))
4544*9880d681SAndroid Build Coastguard Worker         inc = 2;
4545*9880d681SAndroid Build Coastguard Worker       break;
4546*9880d681SAndroid Build Coastguard Worker   }
4547*9880d681SAndroid Build Coastguard Worker 
4548*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4549*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4550*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
4551*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4552*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) { // Writeback
4553*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4554*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4555*9880d681SAndroid Build Coastguard Worker   }
4556*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4557*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4558*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
4559*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
4560*9880d681SAndroid Build Coastguard Worker     if (Rm != 0xD) {
4561*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
4562*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
4563*9880d681SAndroid Build Coastguard Worker     } else
4564*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(0));
4565*9880d681SAndroid Build Coastguard Worker   }
4566*9880d681SAndroid Build Coastguard Worker 
4567*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4568*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4569*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
4570*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4571*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(index));
4572*9880d681SAndroid Build Coastguard Worker 
4573*9880d681SAndroid Build Coastguard Worker   return S;
4574*9880d681SAndroid Build Coastguard Worker }
4575*9880d681SAndroid Build Coastguard Worker 
DecodeVST2LN(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4576*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVST2LN(MCInst &Inst, unsigned Insn,
4577*9880d681SAndroid Build Coastguard Worker                          uint64_t Address, const void *Decoder) {
4578*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4579*9880d681SAndroid Build Coastguard Worker 
4580*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4581*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
4582*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
4583*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
4584*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 10, 2);
4585*9880d681SAndroid Build Coastguard Worker 
4586*9880d681SAndroid Build Coastguard Worker   unsigned align = 0;
4587*9880d681SAndroid Build Coastguard Worker   unsigned index = 0;
4588*9880d681SAndroid Build Coastguard Worker   unsigned inc = 1;
4589*9880d681SAndroid Build Coastguard Worker   switch (size) {
4590*9880d681SAndroid Build Coastguard Worker     default:
4591*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4592*9880d681SAndroid Build Coastguard Worker     case 0:
4593*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 5, 3);
4594*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4595*9880d681SAndroid Build Coastguard Worker         align = 2;
4596*9880d681SAndroid Build Coastguard Worker       break;
4597*9880d681SAndroid Build Coastguard Worker     case 1:
4598*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 6, 2);
4599*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4600*9880d681SAndroid Build Coastguard Worker         align = 4;
4601*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4602*9880d681SAndroid Build Coastguard Worker         inc = 2;
4603*9880d681SAndroid Build Coastguard Worker       break;
4604*9880d681SAndroid Build Coastguard Worker     case 2:
4605*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4606*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4607*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 7, 1);
4608*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1) != 0)
4609*9880d681SAndroid Build Coastguard Worker         align = 8;
4610*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 6, 1))
4611*9880d681SAndroid Build Coastguard Worker         inc = 2;
4612*9880d681SAndroid Build Coastguard Worker       break;
4613*9880d681SAndroid Build Coastguard Worker   }
4614*9880d681SAndroid Build Coastguard Worker 
4615*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) { // Writeback
4616*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4617*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4618*9880d681SAndroid Build Coastguard Worker   }
4619*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4620*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4621*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
4622*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
4623*9880d681SAndroid Build Coastguard Worker     if (Rm != 0xD) {
4624*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
4625*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
4626*9880d681SAndroid Build Coastguard Worker     } else
4627*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(0));
4628*9880d681SAndroid Build Coastguard Worker   }
4629*9880d681SAndroid Build Coastguard Worker 
4630*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4631*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4632*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
4633*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4634*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(index));
4635*9880d681SAndroid Build Coastguard Worker 
4636*9880d681SAndroid Build Coastguard Worker   return S;
4637*9880d681SAndroid Build Coastguard Worker }
4638*9880d681SAndroid Build Coastguard Worker 
4639*9880d681SAndroid Build Coastguard Worker 
DecodeVLD3LN(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4640*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD3LN(MCInst &Inst, unsigned Insn,
4641*9880d681SAndroid Build Coastguard Worker                          uint64_t Address, const void *Decoder) {
4642*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4643*9880d681SAndroid Build Coastguard Worker 
4644*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4645*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
4646*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
4647*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
4648*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 10, 2);
4649*9880d681SAndroid Build Coastguard Worker 
4650*9880d681SAndroid Build Coastguard Worker   unsigned align = 0;
4651*9880d681SAndroid Build Coastguard Worker   unsigned index = 0;
4652*9880d681SAndroid Build Coastguard Worker   unsigned inc = 1;
4653*9880d681SAndroid Build Coastguard Worker   switch (size) {
4654*9880d681SAndroid Build Coastguard Worker     default:
4655*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4656*9880d681SAndroid Build Coastguard Worker     case 0:
4657*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4658*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4659*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 5, 3);
4660*9880d681SAndroid Build Coastguard Worker       break;
4661*9880d681SAndroid Build Coastguard Worker     case 1:
4662*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4663*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4664*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 6, 2);
4665*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4666*9880d681SAndroid Build Coastguard Worker         inc = 2;
4667*9880d681SAndroid Build Coastguard Worker       break;
4668*9880d681SAndroid Build Coastguard Worker     case 2:
4669*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 2))
4670*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4671*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 7, 1);
4672*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 6, 1))
4673*9880d681SAndroid Build Coastguard Worker         inc = 2;
4674*9880d681SAndroid Build Coastguard Worker       break;
4675*9880d681SAndroid Build Coastguard Worker   }
4676*9880d681SAndroid Build Coastguard Worker 
4677*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4678*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4679*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
4680*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4681*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
4682*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4683*9880d681SAndroid Build Coastguard Worker 
4684*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) { // Writeback
4685*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4686*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4687*9880d681SAndroid Build Coastguard Worker   }
4688*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4689*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4690*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
4691*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
4692*9880d681SAndroid Build Coastguard Worker     if (Rm != 0xD) {
4693*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
4694*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4695*9880d681SAndroid Build Coastguard Worker     } else
4696*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(0));
4697*9880d681SAndroid Build Coastguard Worker   }
4698*9880d681SAndroid Build Coastguard Worker 
4699*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4700*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4701*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
4702*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4703*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
4704*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4705*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(index));
4706*9880d681SAndroid Build Coastguard Worker 
4707*9880d681SAndroid Build Coastguard Worker   return S;
4708*9880d681SAndroid Build Coastguard Worker }
4709*9880d681SAndroid Build Coastguard Worker 
DecodeVST3LN(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4710*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVST3LN(MCInst &Inst, unsigned Insn,
4711*9880d681SAndroid Build Coastguard Worker                          uint64_t Address, const void *Decoder) {
4712*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4713*9880d681SAndroid Build Coastguard Worker 
4714*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4715*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
4716*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
4717*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
4718*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 10, 2);
4719*9880d681SAndroid Build Coastguard Worker 
4720*9880d681SAndroid Build Coastguard Worker   unsigned align = 0;
4721*9880d681SAndroid Build Coastguard Worker   unsigned index = 0;
4722*9880d681SAndroid Build Coastguard Worker   unsigned inc = 1;
4723*9880d681SAndroid Build Coastguard Worker   switch (size) {
4724*9880d681SAndroid Build Coastguard Worker     default:
4725*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4726*9880d681SAndroid Build Coastguard Worker     case 0:
4727*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4728*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4729*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 5, 3);
4730*9880d681SAndroid Build Coastguard Worker       break;
4731*9880d681SAndroid Build Coastguard Worker     case 1:
4732*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4733*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4734*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 6, 2);
4735*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4736*9880d681SAndroid Build Coastguard Worker         inc = 2;
4737*9880d681SAndroid Build Coastguard Worker       break;
4738*9880d681SAndroid Build Coastguard Worker     case 2:
4739*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 2))
4740*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail; // UNDEFINED
4741*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 7, 1);
4742*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 6, 1))
4743*9880d681SAndroid Build Coastguard Worker         inc = 2;
4744*9880d681SAndroid Build Coastguard Worker       break;
4745*9880d681SAndroid Build Coastguard Worker   }
4746*9880d681SAndroid Build Coastguard Worker 
4747*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) { // Writeback
4748*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4749*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4750*9880d681SAndroid Build Coastguard Worker   }
4751*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4752*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4753*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
4754*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
4755*9880d681SAndroid Build Coastguard Worker     if (Rm != 0xD) {
4756*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
4757*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4758*9880d681SAndroid Build Coastguard Worker     } else
4759*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(0));
4760*9880d681SAndroid Build Coastguard Worker   }
4761*9880d681SAndroid Build Coastguard Worker 
4762*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4763*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4764*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
4765*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4766*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
4767*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4768*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(index));
4769*9880d681SAndroid Build Coastguard Worker 
4770*9880d681SAndroid Build Coastguard Worker   return S;
4771*9880d681SAndroid Build Coastguard Worker }
4772*9880d681SAndroid Build Coastguard Worker 
4773*9880d681SAndroid Build Coastguard Worker 
DecodeVLD4LN(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4774*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVLD4LN(MCInst &Inst, unsigned Insn,
4775*9880d681SAndroid Build Coastguard Worker                          uint64_t Address, const void *Decoder) {
4776*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4777*9880d681SAndroid Build Coastguard Worker 
4778*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4779*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
4780*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
4781*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
4782*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 10, 2);
4783*9880d681SAndroid Build Coastguard Worker 
4784*9880d681SAndroid Build Coastguard Worker   unsigned align = 0;
4785*9880d681SAndroid Build Coastguard Worker   unsigned index = 0;
4786*9880d681SAndroid Build Coastguard Worker   unsigned inc = 1;
4787*9880d681SAndroid Build Coastguard Worker   switch (size) {
4788*9880d681SAndroid Build Coastguard Worker     default:
4789*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4790*9880d681SAndroid Build Coastguard Worker     case 0:
4791*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4792*9880d681SAndroid Build Coastguard Worker         align = 4;
4793*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 5, 3);
4794*9880d681SAndroid Build Coastguard Worker       break;
4795*9880d681SAndroid Build Coastguard Worker     case 1:
4796*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4797*9880d681SAndroid Build Coastguard Worker         align = 8;
4798*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 6, 2);
4799*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4800*9880d681SAndroid Build Coastguard Worker         inc = 2;
4801*9880d681SAndroid Build Coastguard Worker       break;
4802*9880d681SAndroid Build Coastguard Worker     case 2:
4803*9880d681SAndroid Build Coastguard Worker       switch (fieldFromInstruction(Insn, 4, 2)) {
4804*9880d681SAndroid Build Coastguard Worker         case 0:
4805*9880d681SAndroid Build Coastguard Worker           align = 0; break;
4806*9880d681SAndroid Build Coastguard Worker         case 3:
4807*9880d681SAndroid Build Coastguard Worker           return MCDisassembler::Fail;
4808*9880d681SAndroid Build Coastguard Worker         default:
4809*9880d681SAndroid Build Coastguard Worker           align = 4 << fieldFromInstruction(Insn, 4, 2); break;
4810*9880d681SAndroid Build Coastguard Worker       }
4811*9880d681SAndroid Build Coastguard Worker 
4812*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 7, 1);
4813*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 6, 1))
4814*9880d681SAndroid Build Coastguard Worker         inc = 2;
4815*9880d681SAndroid Build Coastguard Worker       break;
4816*9880d681SAndroid Build Coastguard Worker   }
4817*9880d681SAndroid Build Coastguard Worker 
4818*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4819*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4820*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
4821*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4822*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
4823*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4824*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+3*inc, Address, Decoder)))
4825*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4826*9880d681SAndroid Build Coastguard Worker 
4827*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) { // Writeback
4828*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4829*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4830*9880d681SAndroid Build Coastguard Worker   }
4831*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4832*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4833*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
4834*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
4835*9880d681SAndroid Build Coastguard Worker     if (Rm != 0xD) {
4836*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
4837*9880d681SAndroid Build Coastguard Worker         return MCDisassembler::Fail;
4838*9880d681SAndroid Build Coastguard Worker     } else
4839*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(0));
4840*9880d681SAndroid Build Coastguard Worker   }
4841*9880d681SAndroid Build Coastguard Worker 
4842*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4843*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4844*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
4845*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4846*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
4847*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4848*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+3*inc, Address, Decoder)))
4849*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4850*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(index));
4851*9880d681SAndroid Build Coastguard Worker 
4852*9880d681SAndroid Build Coastguard Worker   return S;
4853*9880d681SAndroid Build Coastguard Worker }
4854*9880d681SAndroid Build Coastguard Worker 
DecodeVST4LN(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4855*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVST4LN(MCInst &Inst, unsigned Insn,
4856*9880d681SAndroid Build Coastguard Worker                          uint64_t Address, const void *Decoder) {
4857*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4858*9880d681SAndroid Build Coastguard Worker 
4859*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
4860*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Insn, 0, 4);
4861*9880d681SAndroid Build Coastguard Worker   unsigned Rd = fieldFromInstruction(Insn, 12, 4);
4862*9880d681SAndroid Build Coastguard Worker   Rd |= fieldFromInstruction(Insn, 22, 1) << 4;
4863*9880d681SAndroid Build Coastguard Worker   unsigned size = fieldFromInstruction(Insn, 10, 2);
4864*9880d681SAndroid Build Coastguard Worker 
4865*9880d681SAndroid Build Coastguard Worker   unsigned align = 0;
4866*9880d681SAndroid Build Coastguard Worker   unsigned index = 0;
4867*9880d681SAndroid Build Coastguard Worker   unsigned inc = 1;
4868*9880d681SAndroid Build Coastguard Worker   switch (size) {
4869*9880d681SAndroid Build Coastguard Worker     default:
4870*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
4871*9880d681SAndroid Build Coastguard Worker     case 0:
4872*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4873*9880d681SAndroid Build Coastguard Worker         align = 4;
4874*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 5, 3);
4875*9880d681SAndroid Build Coastguard Worker       break;
4876*9880d681SAndroid Build Coastguard Worker     case 1:
4877*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 4, 1))
4878*9880d681SAndroid Build Coastguard Worker         align = 8;
4879*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 6, 2);
4880*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 5, 1))
4881*9880d681SAndroid Build Coastguard Worker         inc = 2;
4882*9880d681SAndroid Build Coastguard Worker       break;
4883*9880d681SAndroid Build Coastguard Worker     case 2:
4884*9880d681SAndroid Build Coastguard Worker       switch (fieldFromInstruction(Insn, 4, 2)) {
4885*9880d681SAndroid Build Coastguard Worker         case 0:
4886*9880d681SAndroid Build Coastguard Worker           align = 0; break;
4887*9880d681SAndroid Build Coastguard Worker         case 3:
4888*9880d681SAndroid Build Coastguard Worker           return MCDisassembler::Fail;
4889*9880d681SAndroid Build Coastguard Worker         default:
4890*9880d681SAndroid Build Coastguard Worker           align = 4 << fieldFromInstruction(Insn, 4, 2); break;
4891*9880d681SAndroid Build Coastguard Worker       }
4892*9880d681SAndroid Build Coastguard Worker 
4893*9880d681SAndroid Build Coastguard Worker       index = fieldFromInstruction(Insn, 7, 1);
4894*9880d681SAndroid Build Coastguard Worker       if (fieldFromInstruction(Insn, 6, 1))
4895*9880d681SAndroid Build Coastguard Worker         inc = 2;
4896*9880d681SAndroid Build Coastguard Worker       break;
4897*9880d681SAndroid Build Coastguard Worker   }
4898*9880d681SAndroid Build Coastguard Worker 
4899*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) { // Writeback
4900*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4901*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4902*9880d681SAndroid Build Coastguard Worker   }
4903*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
4904*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4905*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(align));
4906*9880d681SAndroid Build Coastguard Worker   if (Rm != 0xF) {
4907*9880d681SAndroid Build Coastguard Worker     if (Rm != 0xD) {
4908*9880d681SAndroid Build Coastguard Worker       if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
4909*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4910*9880d681SAndroid Build Coastguard Worker     } else
4911*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createReg(0));
4912*9880d681SAndroid Build Coastguard Worker   }
4913*9880d681SAndroid Build Coastguard Worker 
4914*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
4915*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4916*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
4917*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4918*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
4919*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4920*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+3*inc, Address, Decoder)))
4921*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4922*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(index));
4923*9880d681SAndroid Build Coastguard Worker 
4924*9880d681SAndroid Build Coastguard Worker   return S;
4925*9880d681SAndroid Build Coastguard Worker }
4926*9880d681SAndroid Build Coastguard Worker 
DecodeVMOVSRR(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4927*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVMOVSRR(MCInst &Inst, unsigned Insn,
4928*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
4929*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4930*9880d681SAndroid Build Coastguard Worker   unsigned Rt  = fieldFromInstruction(Insn, 12, 4);
4931*9880d681SAndroid Build Coastguard Worker   unsigned Rt2 = fieldFromInstruction(Insn, 16, 4);
4932*9880d681SAndroid Build Coastguard Worker   unsigned Rm  = fieldFromInstruction(Insn,  5, 1);
4933*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
4934*9880d681SAndroid Build Coastguard Worker   Rm |= fieldFromInstruction(Insn, 0, 4) << 1;
4935*9880d681SAndroid Build Coastguard Worker 
4936*9880d681SAndroid Build Coastguard Worker   if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F)
4937*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
4938*9880d681SAndroid Build Coastguard Worker 
4939*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeSPRRegisterClass(Inst, Rm  , Address, Decoder)))
4940*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4941*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeSPRRegisterClass(Inst, Rm+1, Address, Decoder)))
4942*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4943*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt  , Address, Decoder)))
4944*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4945*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt2 , Address, Decoder)))
4946*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4947*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
4948*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4949*9880d681SAndroid Build Coastguard Worker 
4950*9880d681SAndroid Build Coastguard Worker   return S;
4951*9880d681SAndroid Build Coastguard Worker }
4952*9880d681SAndroid Build Coastguard Worker 
DecodeVMOVRRS(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4953*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVMOVRRS(MCInst &Inst, unsigned Insn,
4954*9880d681SAndroid Build Coastguard Worker                                   uint64_t Address, const void *Decoder) {
4955*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4956*9880d681SAndroid Build Coastguard Worker   unsigned Rt  = fieldFromInstruction(Insn, 12, 4);
4957*9880d681SAndroid Build Coastguard Worker   unsigned Rt2 = fieldFromInstruction(Insn, 16, 4);
4958*9880d681SAndroid Build Coastguard Worker   unsigned Rm  = fieldFromInstruction(Insn,  5, 1);
4959*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
4960*9880d681SAndroid Build Coastguard Worker   Rm |= fieldFromInstruction(Insn, 0, 4) << 1;
4961*9880d681SAndroid Build Coastguard Worker 
4962*9880d681SAndroid Build Coastguard Worker   if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F)
4963*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
4964*9880d681SAndroid Build Coastguard Worker 
4965*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt  , Address, Decoder)))
4966*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4967*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRRegisterClass(Inst, Rt2 , Address, Decoder)))
4968*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4969*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeSPRRegisterClass(Inst, Rm  , Address, Decoder)))
4970*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4971*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeSPRRegisterClass(Inst, Rm+1, Address, Decoder)))
4972*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4973*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
4974*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4975*9880d681SAndroid Build Coastguard Worker 
4976*9880d681SAndroid Build Coastguard Worker   return S;
4977*9880d681SAndroid Build Coastguard Worker }
4978*9880d681SAndroid Build Coastguard Worker 
DecodeIT(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4979*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeIT(MCInst &Inst, unsigned Insn,
4980*9880d681SAndroid Build Coastguard Worker                              uint64_t Address, const void *Decoder) {
4981*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
4982*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 4, 4);
4983*9880d681SAndroid Build Coastguard Worker   unsigned mask = fieldFromInstruction(Insn, 0, 4);
4984*9880d681SAndroid Build Coastguard Worker 
4985*9880d681SAndroid Build Coastguard Worker   if (pred == 0xF) {
4986*9880d681SAndroid Build Coastguard Worker     pred = 0xE;
4987*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
4988*9880d681SAndroid Build Coastguard Worker   }
4989*9880d681SAndroid Build Coastguard Worker 
4990*9880d681SAndroid Build Coastguard Worker   if (mask == 0x0)
4991*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
4992*9880d681SAndroid Build Coastguard Worker 
4993*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(pred));
4994*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(mask));
4995*9880d681SAndroid Build Coastguard Worker   return S;
4996*9880d681SAndroid Build Coastguard Worker }
4997*9880d681SAndroid Build Coastguard Worker 
4998*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeT2LDRDPreInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)4999*9880d681SAndroid Build Coastguard Worker DecodeT2LDRDPreInstruction(MCInst &Inst, unsigned Insn,
5000*9880d681SAndroid Build Coastguard Worker                            uint64_t Address, const void *Decoder) {
5001*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
5002*9880d681SAndroid Build Coastguard Worker 
5003*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
5004*9880d681SAndroid Build Coastguard Worker   unsigned Rt2 = fieldFromInstruction(Insn, 8, 4);
5005*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
5006*9880d681SAndroid Build Coastguard Worker   unsigned addr = fieldFromInstruction(Insn, 0, 8);
5007*9880d681SAndroid Build Coastguard Worker   unsigned W = fieldFromInstruction(Insn, 21, 1);
5008*9880d681SAndroid Build Coastguard Worker   unsigned U = fieldFromInstruction(Insn, 23, 1);
5009*9880d681SAndroid Build Coastguard Worker   unsigned P = fieldFromInstruction(Insn, 24, 1);
5010*9880d681SAndroid Build Coastguard Worker   bool writeback = (W == 1) | (P == 0);
5011*9880d681SAndroid Build Coastguard Worker 
5012*9880d681SAndroid Build Coastguard Worker   addr |= (U << 8) | (Rn << 9);
5013*9880d681SAndroid Build Coastguard Worker 
5014*9880d681SAndroid Build Coastguard Worker   if (writeback && (Rn == Rt || Rn == Rt2))
5015*9880d681SAndroid Build Coastguard Worker     Check(S, MCDisassembler::SoftFail);
5016*9880d681SAndroid Build Coastguard Worker   if (Rt == Rt2)
5017*9880d681SAndroid Build Coastguard Worker     Check(S, MCDisassembler::SoftFail);
5018*9880d681SAndroid Build Coastguard Worker 
5019*9880d681SAndroid Build Coastguard Worker   // Rt
5020*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
5021*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5022*9880d681SAndroid Build Coastguard Worker   // Rt2
5023*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rt2, Address, Decoder)))
5024*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5025*9880d681SAndroid Build Coastguard Worker   // Writeback operand
5026*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rn, Address, Decoder)))
5027*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5028*9880d681SAndroid Build Coastguard Worker   // addr
5029*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder)))
5030*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5031*9880d681SAndroid Build Coastguard Worker 
5032*9880d681SAndroid Build Coastguard Worker   return S;
5033*9880d681SAndroid Build Coastguard Worker }
5034*9880d681SAndroid Build Coastguard Worker 
5035*9880d681SAndroid Build Coastguard Worker static DecodeStatus
DecodeT2STRDPreInstruction(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)5036*9880d681SAndroid Build Coastguard Worker DecodeT2STRDPreInstruction(MCInst &Inst, unsigned Insn,
5037*9880d681SAndroid Build Coastguard Worker                            uint64_t Address, const void *Decoder) {
5038*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
5039*9880d681SAndroid Build Coastguard Worker 
5040*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
5041*9880d681SAndroid Build Coastguard Worker   unsigned Rt2 = fieldFromInstruction(Insn, 8, 4);
5042*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
5043*9880d681SAndroid Build Coastguard Worker   unsigned addr = fieldFromInstruction(Insn, 0, 8);
5044*9880d681SAndroid Build Coastguard Worker   unsigned W = fieldFromInstruction(Insn, 21, 1);
5045*9880d681SAndroid Build Coastguard Worker   unsigned U = fieldFromInstruction(Insn, 23, 1);
5046*9880d681SAndroid Build Coastguard Worker   unsigned P = fieldFromInstruction(Insn, 24, 1);
5047*9880d681SAndroid Build Coastguard Worker   bool writeback = (W == 1) | (P == 0);
5048*9880d681SAndroid Build Coastguard Worker 
5049*9880d681SAndroid Build Coastguard Worker   addr |= (U << 8) | (Rn << 9);
5050*9880d681SAndroid Build Coastguard Worker 
5051*9880d681SAndroid Build Coastguard Worker   if (writeback && (Rn == Rt || Rn == Rt2))
5052*9880d681SAndroid Build Coastguard Worker     Check(S, MCDisassembler::SoftFail);
5053*9880d681SAndroid Build Coastguard Worker 
5054*9880d681SAndroid Build Coastguard Worker   // Writeback operand
5055*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rn, Address, Decoder)))
5056*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5057*9880d681SAndroid Build Coastguard Worker   // Rt
5058*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
5059*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5060*9880d681SAndroid Build Coastguard Worker   // Rt2
5061*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecoderGPRRegisterClass(Inst, Rt2, Address, Decoder)))
5062*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5063*9880d681SAndroid Build Coastguard Worker   // addr
5064*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder)))
5065*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5066*9880d681SAndroid Build Coastguard Worker 
5067*9880d681SAndroid Build Coastguard Worker   return S;
5068*9880d681SAndroid Build Coastguard Worker }
5069*9880d681SAndroid Build Coastguard Worker 
DecodeT2Adr(MCInst & Inst,uint32_t Insn,uint64_t Address,const void * Decoder)5070*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2Adr(MCInst &Inst, uint32_t Insn,
5071*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder) {
5072*9880d681SAndroid Build Coastguard Worker   unsigned sign1 = fieldFromInstruction(Insn, 21, 1);
5073*9880d681SAndroid Build Coastguard Worker   unsigned sign2 = fieldFromInstruction(Insn, 23, 1);
5074*9880d681SAndroid Build Coastguard Worker   if (sign1 != sign2) return MCDisassembler::Fail;
5075*9880d681SAndroid Build Coastguard Worker 
5076*9880d681SAndroid Build Coastguard Worker   unsigned Val = fieldFromInstruction(Insn, 0, 8);
5077*9880d681SAndroid Build Coastguard Worker   Val |= fieldFromInstruction(Insn, 12, 3) << 8;
5078*9880d681SAndroid Build Coastguard Worker   Val |= fieldFromInstruction(Insn, 26, 1) << 11;
5079*9880d681SAndroid Build Coastguard Worker   Val |= sign1 << 12;
5080*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(SignExtend32<13>(Val)));
5081*9880d681SAndroid Build Coastguard Worker 
5082*9880d681SAndroid Build Coastguard Worker   return MCDisassembler::Success;
5083*9880d681SAndroid Build Coastguard Worker }
5084*9880d681SAndroid Build Coastguard Worker 
DecodeT2ShifterImmOperand(MCInst & Inst,uint32_t Val,uint64_t Address,const void * Decoder)5085*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeT2ShifterImmOperand(MCInst &Inst, uint32_t Val,
5086*9880d681SAndroid Build Coastguard Worker                                               uint64_t Address,
5087*9880d681SAndroid Build Coastguard Worker                                               const void *Decoder) {
5088*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
5089*9880d681SAndroid Build Coastguard Worker 
5090*9880d681SAndroid Build Coastguard Worker   // Shift of "asr #32" is not allowed in Thumb2 mode.
5091*9880d681SAndroid Build Coastguard Worker   if (Val == 0x20) S = MCDisassembler::Fail;
5092*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(Val));
5093*9880d681SAndroid Build Coastguard Worker   return S;
5094*9880d681SAndroid Build Coastguard Worker }
5095*9880d681SAndroid Build Coastguard Worker 
DecodeSwap(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)5096*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeSwap(MCInst &Inst, unsigned Insn,
5097*9880d681SAndroid Build Coastguard Worker                                uint64_t Address, const void *Decoder) {
5098*9880d681SAndroid Build Coastguard Worker   unsigned Rt   = fieldFromInstruction(Insn, 12, 4);
5099*9880d681SAndroid Build Coastguard Worker   unsigned Rt2  = fieldFromInstruction(Insn, 0,  4);
5100*9880d681SAndroid Build Coastguard Worker   unsigned Rn   = fieldFromInstruction(Insn, 16, 4);
5101*9880d681SAndroid Build Coastguard Worker   unsigned pred = fieldFromInstruction(Insn, 28, 4);
5102*9880d681SAndroid Build Coastguard Worker 
5103*9880d681SAndroid Build Coastguard Worker   if (pred == 0xF)
5104*9880d681SAndroid Build Coastguard Worker     return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
5105*9880d681SAndroid Build Coastguard Worker 
5106*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
5107*9880d681SAndroid Build Coastguard Worker 
5108*9880d681SAndroid Build Coastguard Worker   if (Rt == Rn || Rn == Rt2)
5109*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
5110*9880d681SAndroid Build Coastguard Worker 
5111*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))
5112*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5113*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder)))
5114*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5115*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
5116*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5117*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
5118*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5119*9880d681SAndroid Build Coastguard Worker 
5120*9880d681SAndroid Build Coastguard Worker   return S;
5121*9880d681SAndroid Build Coastguard Worker }
5122*9880d681SAndroid Build Coastguard Worker 
DecodeVCVTD(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)5123*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVCVTD(MCInst &Inst, unsigned Insn,
5124*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder) {
5125*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
5126*9880d681SAndroid Build Coastguard Worker       ((const MCDisassembler *)Decoder)->getSubtargetInfo().getFeatureBits();
5127*9880d681SAndroid Build Coastguard Worker   bool hasFullFP16 = featureBits[ARM::FeatureFullFP16];
5128*9880d681SAndroid Build Coastguard Worker 
5129*9880d681SAndroid Build Coastguard Worker   unsigned Vd = (fieldFromInstruction(Insn, 12, 4) << 0);
5130*9880d681SAndroid Build Coastguard Worker   Vd |= (fieldFromInstruction(Insn, 22, 1) << 4);
5131*9880d681SAndroid Build Coastguard Worker   unsigned Vm = (fieldFromInstruction(Insn, 0, 4) << 0);
5132*9880d681SAndroid Build Coastguard Worker   Vm |= (fieldFromInstruction(Insn, 5, 1) << 4);
5133*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 16, 6);
5134*9880d681SAndroid Build Coastguard Worker   unsigned cmode = fieldFromInstruction(Insn, 8, 4);
5135*9880d681SAndroid Build Coastguard Worker   unsigned op = fieldFromInstruction(Insn, 5, 1);
5136*9880d681SAndroid Build Coastguard Worker 
5137*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
5138*9880d681SAndroid Build Coastguard Worker 
5139*9880d681SAndroid Build Coastguard Worker   // If the top 3 bits of imm are clear, this is a VMOV (immediate)
5140*9880d681SAndroid Build Coastguard Worker   if (!(imm & 0x38)) {
5141*9880d681SAndroid Build Coastguard Worker     if (cmode == 0xF) {
5142*9880d681SAndroid Build Coastguard Worker       if (op == 1) return MCDisassembler::Fail;
5143*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::VMOVv2f32);
5144*9880d681SAndroid Build Coastguard Worker     }
5145*9880d681SAndroid Build Coastguard Worker     if (hasFullFP16) {
5146*9880d681SAndroid Build Coastguard Worker       if (cmode == 0xE) {
5147*9880d681SAndroid Build Coastguard Worker         if (op == 1) {
5148*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMOVv1i64);
5149*9880d681SAndroid Build Coastguard Worker         } else {
5150*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMOVv8i8);
5151*9880d681SAndroid Build Coastguard Worker         }
5152*9880d681SAndroid Build Coastguard Worker       }
5153*9880d681SAndroid Build Coastguard Worker       if (cmode == 0xD) {
5154*9880d681SAndroid Build Coastguard Worker         if (op == 1) {
5155*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMVNv2i32);
5156*9880d681SAndroid Build Coastguard Worker         } else {
5157*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMOVv2i32);
5158*9880d681SAndroid Build Coastguard Worker         }
5159*9880d681SAndroid Build Coastguard Worker       }
5160*9880d681SAndroid Build Coastguard Worker       if (cmode == 0xC) {
5161*9880d681SAndroid Build Coastguard Worker         if (op == 1) {
5162*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMVNv2i32);
5163*9880d681SAndroid Build Coastguard Worker         } else {
5164*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMOVv2i32);
5165*9880d681SAndroid Build Coastguard Worker         }
5166*9880d681SAndroid Build Coastguard Worker       }
5167*9880d681SAndroid Build Coastguard Worker     }
5168*9880d681SAndroid Build Coastguard Worker     return DecodeNEONModImmInstruction(Inst, Insn, Address, Decoder);
5169*9880d681SAndroid Build Coastguard Worker   }
5170*9880d681SAndroid Build Coastguard Worker 
5171*9880d681SAndroid Build Coastguard Worker   if (!(imm & 0x20)) return MCDisassembler::Fail;
5172*9880d681SAndroid Build Coastguard Worker 
5173*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Vd, Address, Decoder)))
5174*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5175*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeDPRRegisterClass(Inst, Vm, Address, Decoder)))
5176*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5177*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(64 - imm));
5178*9880d681SAndroid Build Coastguard Worker 
5179*9880d681SAndroid Build Coastguard Worker   return S;
5180*9880d681SAndroid Build Coastguard Worker }
5181*9880d681SAndroid Build Coastguard Worker 
DecodeVCVTQ(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)5182*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVCVTQ(MCInst &Inst, unsigned Insn,
5183*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder) {
5184*9880d681SAndroid Build Coastguard Worker   const FeatureBitset &featureBits =
5185*9880d681SAndroid Build Coastguard Worker       ((const MCDisassembler *)Decoder)->getSubtargetInfo().getFeatureBits();
5186*9880d681SAndroid Build Coastguard Worker   bool hasFullFP16 = featureBits[ARM::FeatureFullFP16];
5187*9880d681SAndroid Build Coastguard Worker 
5188*9880d681SAndroid Build Coastguard Worker   unsigned Vd = (fieldFromInstruction(Insn, 12, 4) << 0);
5189*9880d681SAndroid Build Coastguard Worker   Vd |= (fieldFromInstruction(Insn, 22, 1) << 4);
5190*9880d681SAndroid Build Coastguard Worker   unsigned Vm = (fieldFromInstruction(Insn, 0, 4) << 0);
5191*9880d681SAndroid Build Coastguard Worker   Vm |= (fieldFromInstruction(Insn, 5, 1) << 4);
5192*9880d681SAndroid Build Coastguard Worker   unsigned imm = fieldFromInstruction(Insn, 16, 6);
5193*9880d681SAndroid Build Coastguard Worker   unsigned cmode = fieldFromInstruction(Insn, 8, 4);
5194*9880d681SAndroid Build Coastguard Worker   unsigned op = fieldFromInstruction(Insn, 5, 1);
5195*9880d681SAndroid Build Coastguard Worker 
5196*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
5197*9880d681SAndroid Build Coastguard Worker 
5198*9880d681SAndroid Build Coastguard Worker   // If the top 3 bits of imm are clear, this is a VMOV (immediate)
5199*9880d681SAndroid Build Coastguard Worker   if (!(imm & 0x38)) {
5200*9880d681SAndroid Build Coastguard Worker     if (cmode == 0xF) {
5201*9880d681SAndroid Build Coastguard Worker       if (op == 1) return MCDisassembler::Fail;
5202*9880d681SAndroid Build Coastguard Worker       Inst.setOpcode(ARM::VMOVv4f32);
5203*9880d681SAndroid Build Coastguard Worker     }
5204*9880d681SAndroid Build Coastguard Worker     if (hasFullFP16) {
5205*9880d681SAndroid Build Coastguard Worker       if (cmode == 0xE) {
5206*9880d681SAndroid Build Coastguard Worker         if (op == 1) {
5207*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMOVv2i64);
5208*9880d681SAndroid Build Coastguard Worker         } else {
5209*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMOVv16i8);
5210*9880d681SAndroid Build Coastguard Worker         }
5211*9880d681SAndroid Build Coastguard Worker       }
5212*9880d681SAndroid Build Coastguard Worker       if (cmode == 0xD) {
5213*9880d681SAndroid Build Coastguard Worker         if (op == 1) {
5214*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMVNv4i32);
5215*9880d681SAndroid Build Coastguard Worker         } else {
5216*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMOVv4i32);
5217*9880d681SAndroid Build Coastguard Worker         }
5218*9880d681SAndroid Build Coastguard Worker       }
5219*9880d681SAndroid Build Coastguard Worker       if (cmode == 0xC) {
5220*9880d681SAndroid Build Coastguard Worker         if (op == 1) {
5221*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMVNv4i32);
5222*9880d681SAndroid Build Coastguard Worker         } else {
5223*9880d681SAndroid Build Coastguard Worker           Inst.setOpcode(ARM::VMOVv4i32);
5224*9880d681SAndroid Build Coastguard Worker         }
5225*9880d681SAndroid Build Coastguard Worker       }
5226*9880d681SAndroid Build Coastguard Worker     }
5227*9880d681SAndroid Build Coastguard Worker     return DecodeNEONModImmInstruction(Inst, Insn, Address, Decoder);
5228*9880d681SAndroid Build Coastguard Worker   }
5229*9880d681SAndroid Build Coastguard Worker 
5230*9880d681SAndroid Build Coastguard Worker   if (!(imm & 0x20)) return MCDisassembler::Fail;
5231*9880d681SAndroid Build Coastguard Worker 
5232*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeQPRRegisterClass(Inst, Vd, Address, Decoder)))
5233*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5234*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeQPRRegisterClass(Inst, Vm, Address, Decoder)))
5235*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5236*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(64 - imm));
5237*9880d681SAndroid Build Coastguard Worker 
5238*9880d681SAndroid Build Coastguard Worker   return S;
5239*9880d681SAndroid Build Coastguard Worker }
5240*9880d681SAndroid Build Coastguard Worker 
DecodeLDR(MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)5241*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val,
5242*9880d681SAndroid Build Coastguard Worker                                 uint64_t Address, const void *Decoder) {
5243*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
5244*9880d681SAndroid Build Coastguard Worker 
5245*9880d681SAndroid Build Coastguard Worker   unsigned Rn = fieldFromInstruction(Val, 16, 4);
5246*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Val, 12, 4);
5247*9880d681SAndroid Build Coastguard Worker   unsigned Rm = fieldFromInstruction(Val, 0, 4);
5248*9880d681SAndroid Build Coastguard Worker   Rm |= (fieldFromInstruction(Val, 23, 1) << 4);
5249*9880d681SAndroid Build Coastguard Worker   unsigned Cond = fieldFromInstruction(Val, 28, 4);
5250*9880d681SAndroid Build Coastguard Worker 
5251*9880d681SAndroid Build Coastguard Worker   if (fieldFromInstruction(Val, 8, 4) != 0 || Rn == Rt)
5252*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
5253*9880d681SAndroid Build Coastguard Worker 
5254*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))
5255*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5256*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
5257*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5258*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodeAddrMode7Operand(Inst, Rn, Address, Decoder)))
5259*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5260*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePostIdxReg(Inst, Rm, Address, Decoder)))
5261*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5262*9880d681SAndroid Build Coastguard Worker   if (!Check(S, DecodePredicateOperand(Inst, Cond, Address, Decoder)))
5263*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5264*9880d681SAndroid Build Coastguard Worker 
5265*9880d681SAndroid Build Coastguard Worker   return S;
5266*9880d681SAndroid Build Coastguard Worker }
5267*9880d681SAndroid Build Coastguard Worker 
DecoderForMRRC2AndMCRR2(llvm::MCInst & Inst,unsigned Val,uint64_t Address,const void * Decoder)5268*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecoderForMRRC2AndMCRR2(llvm::MCInst &Inst, unsigned Val,
5269*9880d681SAndroid Build Coastguard Worker                                             uint64_t Address, const void *Decoder) {
5270*9880d681SAndroid Build Coastguard Worker 
5271*9880d681SAndroid Build Coastguard Worker   DecodeStatus S = MCDisassembler::Success;
5272*9880d681SAndroid Build Coastguard Worker 
5273*9880d681SAndroid Build Coastguard Worker   unsigned CRm = fieldFromInstruction(Val, 0, 4);
5274*9880d681SAndroid Build Coastguard Worker   unsigned opc1 = fieldFromInstruction(Val, 4, 4);
5275*9880d681SAndroid Build Coastguard Worker   unsigned cop = fieldFromInstruction(Val, 8, 4);
5276*9880d681SAndroid Build Coastguard Worker   unsigned Rt = fieldFromInstruction(Val, 12, 4);
5277*9880d681SAndroid Build Coastguard Worker   unsigned Rt2 = fieldFromInstruction(Val, 16, 4);
5278*9880d681SAndroid Build Coastguard Worker 
5279*9880d681SAndroid Build Coastguard Worker   if ((cop & ~0x1) == 0xa)
5280*9880d681SAndroid Build Coastguard Worker     return MCDisassembler::Fail;
5281*9880d681SAndroid Build Coastguard Worker 
5282*9880d681SAndroid Build Coastguard Worker   if (Rt == Rt2)
5283*9880d681SAndroid Build Coastguard Worker     S = MCDisassembler::SoftFail;
5284*9880d681SAndroid Build Coastguard Worker 
5285*9880d681SAndroid Build Coastguard Worker   // We have to check if the instruction is MRRC2
5286*9880d681SAndroid Build Coastguard Worker   // or MCRR2 when constructing the operands for
5287*9880d681SAndroid Build Coastguard Worker   // Inst. Reason is because MRRC2 stores to two
5288*9880d681SAndroid Build Coastguard Worker   // registers so it's tablegen desc has has two
5289*9880d681SAndroid Build Coastguard Worker   // outputs whereas MCRR doesn't store to any
5290*9880d681SAndroid Build Coastguard Worker   // registers so all of it's operands are listed
5291*9880d681SAndroid Build Coastguard Worker   // as inputs, therefore the operand order for
5292*9880d681SAndroid Build Coastguard Worker   // MRRC2 needs to be [Rt, Rt2, cop, opc1, CRm]
5293*9880d681SAndroid Build Coastguard Worker   // and MCRR2 operand order is [cop, opc1, Rt, Rt2, CRm]
5294*9880d681SAndroid Build Coastguard Worker 
5295*9880d681SAndroid Build Coastguard Worker   if (Inst.getOpcode() == ARM::MRRC2) {
5296*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))
5297*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
5298*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder)))
5299*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
5300*9880d681SAndroid Build Coastguard Worker   }
5301*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(cop));
5302*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(opc1));
5303*9880d681SAndroid Build Coastguard Worker   if (Inst.getOpcode() == ARM::MCRR2) {
5304*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))
5305*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
5306*9880d681SAndroid Build Coastguard Worker     if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder)))
5307*9880d681SAndroid Build Coastguard Worker       return MCDisassembler::Fail;
5308*9880d681SAndroid Build Coastguard Worker   }
5309*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createImm(CRm));
5310*9880d681SAndroid Build Coastguard Worker 
5311*9880d681SAndroid Build Coastguard Worker   return S;
5312*9880d681SAndroid Build Coastguard Worker }
5313*9880d681SAndroid Build Coastguard Worker 
5314