1*9880d681SAndroid Build Coastguard Worker //===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
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 "ARMFeatures.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/ADT/STLExtras.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSwitch.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Triple.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCDisassembler/MCDisassembler.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCELFStreamer.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrDesc.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectFileInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmLexer.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmParser.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmParserUtils.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCTargetAsmParser.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSection.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ARMBuildAttributes.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ARMEHABI.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/COFF.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
44*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ELF.h"
45*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
46*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/SourceMgr.h"
47*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetParser.h"
48*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
49*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker using namespace llvm;
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker namespace {
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker class ARMOperand;
56*9880d681SAndroid Build Coastguard Worker
57*9880d681SAndroid Build Coastguard Worker enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker class UnwindContext {
60*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser;
61*9880d681SAndroid Build Coastguard Worker
62*9880d681SAndroid Build Coastguard Worker typedef SmallVector<SMLoc, 4> Locs;
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker Locs FnStartLocs;
65*9880d681SAndroid Build Coastguard Worker Locs CantUnwindLocs;
66*9880d681SAndroid Build Coastguard Worker Locs PersonalityLocs;
67*9880d681SAndroid Build Coastguard Worker Locs PersonalityIndexLocs;
68*9880d681SAndroid Build Coastguard Worker Locs HandlerDataLocs;
69*9880d681SAndroid Build Coastguard Worker int FPReg;
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker public:
UnwindContext(MCAsmParser & P)72*9880d681SAndroid Build Coastguard Worker UnwindContext(MCAsmParser &P) : Parser(P), FPReg(ARM::SP) {}
73*9880d681SAndroid Build Coastguard Worker
hasFnStart() const74*9880d681SAndroid Build Coastguard Worker bool hasFnStart() const { return !FnStartLocs.empty(); }
cantUnwind() const75*9880d681SAndroid Build Coastguard Worker bool cantUnwind() const { return !CantUnwindLocs.empty(); }
hasHandlerData() const76*9880d681SAndroid Build Coastguard Worker bool hasHandlerData() const { return !HandlerDataLocs.empty(); }
hasPersonality() const77*9880d681SAndroid Build Coastguard Worker bool hasPersonality() const {
78*9880d681SAndroid Build Coastguard Worker return !(PersonalityLocs.empty() && PersonalityIndexLocs.empty());
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker
recordFnStart(SMLoc L)81*9880d681SAndroid Build Coastguard Worker void recordFnStart(SMLoc L) { FnStartLocs.push_back(L); }
recordCantUnwind(SMLoc L)82*9880d681SAndroid Build Coastguard Worker void recordCantUnwind(SMLoc L) { CantUnwindLocs.push_back(L); }
recordPersonality(SMLoc L)83*9880d681SAndroid Build Coastguard Worker void recordPersonality(SMLoc L) { PersonalityLocs.push_back(L); }
recordHandlerData(SMLoc L)84*9880d681SAndroid Build Coastguard Worker void recordHandlerData(SMLoc L) { HandlerDataLocs.push_back(L); }
recordPersonalityIndex(SMLoc L)85*9880d681SAndroid Build Coastguard Worker void recordPersonalityIndex(SMLoc L) { PersonalityIndexLocs.push_back(L); }
86*9880d681SAndroid Build Coastguard Worker
saveFPReg(int Reg)87*9880d681SAndroid Build Coastguard Worker void saveFPReg(int Reg) { FPReg = Reg; }
getFPReg() const88*9880d681SAndroid Build Coastguard Worker int getFPReg() const { return FPReg; }
89*9880d681SAndroid Build Coastguard Worker
emitFnStartLocNotes() const90*9880d681SAndroid Build Coastguard Worker void emitFnStartLocNotes() const {
91*9880d681SAndroid Build Coastguard Worker for (Locs::const_iterator FI = FnStartLocs.begin(), FE = FnStartLocs.end();
92*9880d681SAndroid Build Coastguard Worker FI != FE; ++FI)
93*9880d681SAndroid Build Coastguard Worker Parser.Note(*FI, ".fnstart was specified here");
94*9880d681SAndroid Build Coastguard Worker }
emitCantUnwindLocNotes() const95*9880d681SAndroid Build Coastguard Worker void emitCantUnwindLocNotes() const {
96*9880d681SAndroid Build Coastguard Worker for (Locs::const_iterator UI = CantUnwindLocs.begin(),
97*9880d681SAndroid Build Coastguard Worker UE = CantUnwindLocs.end(); UI != UE; ++UI)
98*9880d681SAndroid Build Coastguard Worker Parser.Note(*UI, ".cantunwind was specified here");
99*9880d681SAndroid Build Coastguard Worker }
emitHandlerDataLocNotes() const100*9880d681SAndroid Build Coastguard Worker void emitHandlerDataLocNotes() const {
101*9880d681SAndroid Build Coastguard Worker for (Locs::const_iterator HI = HandlerDataLocs.begin(),
102*9880d681SAndroid Build Coastguard Worker HE = HandlerDataLocs.end(); HI != HE; ++HI)
103*9880d681SAndroid Build Coastguard Worker Parser.Note(*HI, ".handlerdata was specified here");
104*9880d681SAndroid Build Coastguard Worker }
emitPersonalityLocNotes() const105*9880d681SAndroid Build Coastguard Worker void emitPersonalityLocNotes() const {
106*9880d681SAndroid Build Coastguard Worker for (Locs::const_iterator PI = PersonalityLocs.begin(),
107*9880d681SAndroid Build Coastguard Worker PE = PersonalityLocs.end(),
108*9880d681SAndroid Build Coastguard Worker PII = PersonalityIndexLocs.begin(),
109*9880d681SAndroid Build Coastguard Worker PIE = PersonalityIndexLocs.end();
110*9880d681SAndroid Build Coastguard Worker PI != PE || PII != PIE;) {
111*9880d681SAndroid Build Coastguard Worker if (PI != PE && (PII == PIE || PI->getPointer() < PII->getPointer()))
112*9880d681SAndroid Build Coastguard Worker Parser.Note(*PI++, ".personality was specified here");
113*9880d681SAndroid Build Coastguard Worker else if (PII != PIE && (PI == PE || PII->getPointer() < PI->getPointer()))
114*9880d681SAndroid Build Coastguard Worker Parser.Note(*PII++, ".personalityindex was specified here");
115*9880d681SAndroid Build Coastguard Worker else
116*9880d681SAndroid Build Coastguard Worker llvm_unreachable(".personality and .personalityindex cannot be "
117*9880d681SAndroid Build Coastguard Worker "at the same location");
118*9880d681SAndroid Build Coastguard Worker }
119*9880d681SAndroid Build Coastguard Worker }
120*9880d681SAndroid Build Coastguard Worker
reset()121*9880d681SAndroid Build Coastguard Worker void reset() {
122*9880d681SAndroid Build Coastguard Worker FnStartLocs = Locs();
123*9880d681SAndroid Build Coastguard Worker CantUnwindLocs = Locs();
124*9880d681SAndroid Build Coastguard Worker PersonalityLocs = Locs();
125*9880d681SAndroid Build Coastguard Worker HandlerDataLocs = Locs();
126*9880d681SAndroid Build Coastguard Worker PersonalityIndexLocs = Locs();
127*9880d681SAndroid Build Coastguard Worker FPReg = ARM::SP;
128*9880d681SAndroid Build Coastguard Worker }
129*9880d681SAndroid Build Coastguard Worker };
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker class ARMAsmParser : public MCTargetAsmParser {
132*9880d681SAndroid Build Coastguard Worker const MCInstrInfo &MII;
133*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo *MRI;
134*9880d681SAndroid Build Coastguard Worker UnwindContext UC;
135*9880d681SAndroid Build Coastguard Worker
getTargetStreamer()136*9880d681SAndroid Build Coastguard Worker ARMTargetStreamer &getTargetStreamer() {
137*9880d681SAndroid Build Coastguard Worker assert(getParser().getStreamer().getTargetStreamer() &&
138*9880d681SAndroid Build Coastguard Worker "do not have a target streamer");
139*9880d681SAndroid Build Coastguard Worker MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
140*9880d681SAndroid Build Coastguard Worker return static_cast<ARMTargetStreamer &>(TS);
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker
143*9880d681SAndroid Build Coastguard Worker // Map of register aliases registers via the .req directive.
144*9880d681SAndroid Build Coastguard Worker StringMap<unsigned> RegisterReqs;
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker bool NextSymbolIsThumb;
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker struct {
149*9880d681SAndroid Build Coastguard Worker ARMCC::CondCodes Cond; // Condition for IT block.
150*9880d681SAndroid Build Coastguard Worker unsigned Mask:4; // Condition mask for instructions.
151*9880d681SAndroid Build Coastguard Worker // Starting at first 1 (from lsb).
152*9880d681SAndroid Build Coastguard Worker // '1' condition as indicated in IT.
153*9880d681SAndroid Build Coastguard Worker // '0' inverse of condition (else).
154*9880d681SAndroid Build Coastguard Worker // Count of instructions in IT block is
155*9880d681SAndroid Build Coastguard Worker // 4 - trailingzeroes(mask)
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker bool FirstCond; // Explicit flag for when we're parsing the
158*9880d681SAndroid Build Coastguard Worker // First instruction in the IT block. It's
159*9880d681SAndroid Build Coastguard Worker // implied in the mask, so needs special
160*9880d681SAndroid Build Coastguard Worker // handling.
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Worker unsigned CurPosition; // Current position in parsing of IT
163*9880d681SAndroid Build Coastguard Worker // block. In range [0,3]. Initialized
164*9880d681SAndroid Build Coastguard Worker // according to count of instructions in block.
165*9880d681SAndroid Build Coastguard Worker // ~0U if no active IT block.
166*9880d681SAndroid Build Coastguard Worker } ITState;
inITBlock()167*9880d681SAndroid Build Coastguard Worker bool inITBlock() { return ITState.CurPosition != ~0U; }
lastInITBlock()168*9880d681SAndroid Build Coastguard Worker bool lastInITBlock() {
169*9880d681SAndroid Build Coastguard Worker return ITState.CurPosition == 4 - countTrailingZeros(ITState.Mask);
170*9880d681SAndroid Build Coastguard Worker }
forwardITPosition()171*9880d681SAndroid Build Coastguard Worker void forwardITPosition() {
172*9880d681SAndroid Build Coastguard Worker if (!inITBlock()) return;
173*9880d681SAndroid Build Coastguard Worker // Move to the next instruction in the IT block, if there is one. If not,
174*9880d681SAndroid Build Coastguard Worker // mark the block as done.
175*9880d681SAndroid Build Coastguard Worker unsigned TZ = countTrailingZeros(ITState.Mask);
176*9880d681SAndroid Build Coastguard Worker if (++ITState.CurPosition == 5 - TZ)
177*9880d681SAndroid Build Coastguard Worker ITState.CurPosition = ~0U; // Done with the IT block after this.
178*9880d681SAndroid Build Coastguard Worker }
179*9880d681SAndroid Build Coastguard Worker
Note(SMLoc L,const Twine & Msg,ArrayRef<SMRange> Ranges=None)180*9880d681SAndroid Build Coastguard Worker void Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) {
181*9880d681SAndroid Build Coastguard Worker return getParser().Note(L, Msg, Ranges);
182*9880d681SAndroid Build Coastguard Worker }
Warning(SMLoc L,const Twine & Msg,ArrayRef<SMRange> Ranges=None)183*9880d681SAndroid Build Coastguard Worker bool Warning(SMLoc L, const Twine &Msg,
184*9880d681SAndroid Build Coastguard Worker ArrayRef<SMRange> Ranges = None) {
185*9880d681SAndroid Build Coastguard Worker return getParser().Warning(L, Msg, Ranges);
186*9880d681SAndroid Build Coastguard Worker }
Error(SMLoc L,const Twine & Msg,ArrayRef<SMRange> Ranges=None)187*9880d681SAndroid Build Coastguard Worker bool Error(SMLoc L, const Twine &Msg,
188*9880d681SAndroid Build Coastguard Worker ArrayRef<SMRange> Ranges = None) {
189*9880d681SAndroid Build Coastguard Worker return getParser().Error(L, Msg, Ranges);
190*9880d681SAndroid Build Coastguard Worker }
191*9880d681SAndroid Build Coastguard Worker
192*9880d681SAndroid Build Coastguard Worker bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands,
193*9880d681SAndroid Build Coastguard Worker unsigned ListNo, bool IsARPop = false);
194*9880d681SAndroid Build Coastguard Worker bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands,
195*9880d681SAndroid Build Coastguard Worker unsigned ListNo);
196*9880d681SAndroid Build Coastguard Worker
197*9880d681SAndroid Build Coastguard Worker int tryParseRegister();
198*9880d681SAndroid Build Coastguard Worker bool tryParseRegisterWithWriteBack(OperandVector &);
199*9880d681SAndroid Build Coastguard Worker int tryParseShiftRegister(OperandVector &);
200*9880d681SAndroid Build Coastguard Worker bool parseRegisterList(OperandVector &);
201*9880d681SAndroid Build Coastguard Worker bool parseMemory(OperandVector &);
202*9880d681SAndroid Build Coastguard Worker bool parseOperand(OperandVector &, StringRef Mnemonic);
203*9880d681SAndroid Build Coastguard Worker bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
204*9880d681SAndroid Build Coastguard Worker bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
205*9880d681SAndroid Build Coastguard Worker unsigned &ShiftAmount);
206*9880d681SAndroid Build Coastguard Worker bool parseLiteralValues(unsigned Size, SMLoc L);
207*9880d681SAndroid Build Coastguard Worker bool parseDirectiveThumb(SMLoc L);
208*9880d681SAndroid Build Coastguard Worker bool parseDirectiveARM(SMLoc L);
209*9880d681SAndroid Build Coastguard Worker bool parseDirectiveThumbFunc(SMLoc L);
210*9880d681SAndroid Build Coastguard Worker bool parseDirectiveCode(SMLoc L);
211*9880d681SAndroid Build Coastguard Worker bool parseDirectiveSyntax(SMLoc L);
212*9880d681SAndroid Build Coastguard Worker bool parseDirectiveReq(StringRef Name, SMLoc L);
213*9880d681SAndroid Build Coastguard Worker bool parseDirectiveUnreq(SMLoc L);
214*9880d681SAndroid Build Coastguard Worker bool parseDirectiveArch(SMLoc L);
215*9880d681SAndroid Build Coastguard Worker bool parseDirectiveEabiAttr(SMLoc L);
216*9880d681SAndroid Build Coastguard Worker bool parseDirectiveCPU(SMLoc L);
217*9880d681SAndroid Build Coastguard Worker bool parseDirectiveFPU(SMLoc L);
218*9880d681SAndroid Build Coastguard Worker bool parseDirectiveFnStart(SMLoc L);
219*9880d681SAndroid Build Coastguard Worker bool parseDirectiveFnEnd(SMLoc L);
220*9880d681SAndroid Build Coastguard Worker bool parseDirectiveCantUnwind(SMLoc L);
221*9880d681SAndroid Build Coastguard Worker bool parseDirectivePersonality(SMLoc L);
222*9880d681SAndroid Build Coastguard Worker bool parseDirectiveHandlerData(SMLoc L);
223*9880d681SAndroid Build Coastguard Worker bool parseDirectiveSetFP(SMLoc L);
224*9880d681SAndroid Build Coastguard Worker bool parseDirectivePad(SMLoc L);
225*9880d681SAndroid Build Coastguard Worker bool parseDirectiveRegSave(SMLoc L, bool IsVector);
226*9880d681SAndroid Build Coastguard Worker bool parseDirectiveInst(SMLoc L, char Suffix = '\0');
227*9880d681SAndroid Build Coastguard Worker bool parseDirectiveLtorg(SMLoc L);
228*9880d681SAndroid Build Coastguard Worker bool parseDirectiveEven(SMLoc L);
229*9880d681SAndroid Build Coastguard Worker bool parseDirectivePersonalityIndex(SMLoc L);
230*9880d681SAndroid Build Coastguard Worker bool parseDirectiveUnwindRaw(SMLoc L);
231*9880d681SAndroid Build Coastguard Worker bool parseDirectiveTLSDescSeq(SMLoc L);
232*9880d681SAndroid Build Coastguard Worker bool parseDirectiveMovSP(SMLoc L);
233*9880d681SAndroid Build Coastguard Worker bool parseDirectiveObjectArch(SMLoc L);
234*9880d681SAndroid Build Coastguard Worker bool parseDirectiveArchExtension(SMLoc L);
235*9880d681SAndroid Build Coastguard Worker bool parseDirectiveAlign(SMLoc L);
236*9880d681SAndroid Build Coastguard Worker bool parseDirectiveThumbSet(SMLoc L);
237*9880d681SAndroid Build Coastguard Worker
238*9880d681SAndroid Build Coastguard Worker StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
239*9880d681SAndroid Build Coastguard Worker bool &CarrySetting, unsigned &ProcessorIMod,
240*9880d681SAndroid Build Coastguard Worker StringRef &ITMask);
241*9880d681SAndroid Build Coastguard Worker void getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst,
242*9880d681SAndroid Build Coastguard Worker bool &CanAcceptCarrySet,
243*9880d681SAndroid Build Coastguard Worker bool &CanAcceptPredicationCode);
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting,
246*9880d681SAndroid Build Coastguard Worker OperandVector &Operands);
isThumb() const247*9880d681SAndroid Build Coastguard Worker bool isThumb() const {
248*9880d681SAndroid Build Coastguard Worker // FIXME: Can tablegen auto-generate this?
249*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::ModeThumb];
250*9880d681SAndroid Build Coastguard Worker }
isThumbOne() const251*9880d681SAndroid Build Coastguard Worker bool isThumbOne() const {
252*9880d681SAndroid Build Coastguard Worker return isThumb() && !getSTI().getFeatureBits()[ARM::FeatureThumb2];
253*9880d681SAndroid Build Coastguard Worker }
isThumbTwo() const254*9880d681SAndroid Build Coastguard Worker bool isThumbTwo() const {
255*9880d681SAndroid Build Coastguard Worker return isThumb() && getSTI().getFeatureBits()[ARM::FeatureThumb2];
256*9880d681SAndroid Build Coastguard Worker }
hasThumb() const257*9880d681SAndroid Build Coastguard Worker bool hasThumb() const {
258*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::HasV4TOps];
259*9880d681SAndroid Build Coastguard Worker }
hasThumb2() const260*9880d681SAndroid Build Coastguard Worker bool hasThumb2() const {
261*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::FeatureThumb2];
262*9880d681SAndroid Build Coastguard Worker }
hasV6Ops() const263*9880d681SAndroid Build Coastguard Worker bool hasV6Ops() const {
264*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::HasV6Ops];
265*9880d681SAndroid Build Coastguard Worker }
hasV6T2Ops() const266*9880d681SAndroid Build Coastguard Worker bool hasV6T2Ops() const {
267*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::HasV6T2Ops];
268*9880d681SAndroid Build Coastguard Worker }
hasV6MOps() const269*9880d681SAndroid Build Coastguard Worker bool hasV6MOps() const {
270*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::HasV6MOps];
271*9880d681SAndroid Build Coastguard Worker }
hasV7Ops() const272*9880d681SAndroid Build Coastguard Worker bool hasV7Ops() const {
273*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::HasV7Ops];
274*9880d681SAndroid Build Coastguard Worker }
hasV8Ops() const275*9880d681SAndroid Build Coastguard Worker bool hasV8Ops() const {
276*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::HasV8Ops];
277*9880d681SAndroid Build Coastguard Worker }
hasV8MBaseline() const278*9880d681SAndroid Build Coastguard Worker bool hasV8MBaseline() const {
279*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::HasV8MBaselineOps];
280*9880d681SAndroid Build Coastguard Worker }
hasV8MMainline() const281*9880d681SAndroid Build Coastguard Worker bool hasV8MMainline() const {
282*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::HasV8MMainlineOps];
283*9880d681SAndroid Build Coastguard Worker }
has8MSecExt() const284*9880d681SAndroid Build Coastguard Worker bool has8MSecExt() const {
285*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::Feature8MSecExt];
286*9880d681SAndroid Build Coastguard Worker }
hasARM() const287*9880d681SAndroid Build Coastguard Worker bool hasARM() const {
288*9880d681SAndroid Build Coastguard Worker return !getSTI().getFeatureBits()[ARM::FeatureNoARM];
289*9880d681SAndroid Build Coastguard Worker }
hasDSP() const290*9880d681SAndroid Build Coastguard Worker bool hasDSP() const {
291*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::FeatureDSP];
292*9880d681SAndroid Build Coastguard Worker }
hasD16() const293*9880d681SAndroid Build Coastguard Worker bool hasD16() const {
294*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::FeatureD16];
295*9880d681SAndroid Build Coastguard Worker }
hasV8_1aOps() const296*9880d681SAndroid Build Coastguard Worker bool hasV8_1aOps() const {
297*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::HasV8_1aOps];
298*9880d681SAndroid Build Coastguard Worker }
hasRAS() const299*9880d681SAndroid Build Coastguard Worker bool hasRAS() const {
300*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::FeatureRAS];
301*9880d681SAndroid Build Coastguard Worker }
302*9880d681SAndroid Build Coastguard Worker
SwitchMode()303*9880d681SAndroid Build Coastguard Worker void SwitchMode() {
304*9880d681SAndroid Build Coastguard Worker MCSubtargetInfo &STI = copySTI();
305*9880d681SAndroid Build Coastguard Worker uint64_t FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
306*9880d681SAndroid Build Coastguard Worker setAvailableFeatures(FB);
307*9880d681SAndroid Build Coastguard Worker }
308*9880d681SAndroid Build Coastguard Worker void FixModeAfterArchChange(bool WasThumb, SMLoc Loc);
isMClass() const309*9880d681SAndroid Build Coastguard Worker bool isMClass() const {
310*9880d681SAndroid Build Coastguard Worker return getSTI().getFeatureBits()[ARM::FeatureMClass];
311*9880d681SAndroid Build Coastguard Worker }
312*9880d681SAndroid Build Coastguard Worker
313*9880d681SAndroid Build Coastguard Worker /// @name Auto-generated Match Functions
314*9880d681SAndroid Build Coastguard Worker /// {
315*9880d681SAndroid Build Coastguard Worker
316*9880d681SAndroid Build Coastguard Worker #define GET_ASSEMBLER_HEADER
317*9880d681SAndroid Build Coastguard Worker #include "ARMGenAsmMatcher.inc"
318*9880d681SAndroid Build Coastguard Worker
319*9880d681SAndroid Build Coastguard Worker /// }
320*9880d681SAndroid Build Coastguard Worker
321*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseITCondCode(OperandVector &);
322*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseCoprocNumOperand(OperandVector &);
323*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseCoprocRegOperand(OperandVector &);
324*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseCoprocOptionOperand(OperandVector &);
325*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseMemBarrierOptOperand(OperandVector &);
326*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseInstSyncBarrierOptOperand(OperandVector &);
327*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseProcIFlagsOperand(OperandVector &);
328*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseMSRMaskOperand(OperandVector &);
329*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseBankedRegOperand(OperandVector &);
330*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parsePKHImm(OperandVector &O, StringRef Op, int Low,
331*9880d681SAndroid Build Coastguard Worker int High);
parsePKHLSLImm(OperandVector & O)332*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parsePKHLSLImm(OperandVector &O) {
333*9880d681SAndroid Build Coastguard Worker return parsePKHImm(O, "lsl", 0, 31);
334*9880d681SAndroid Build Coastguard Worker }
parsePKHASRImm(OperandVector & O)335*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parsePKHASRImm(OperandVector &O) {
336*9880d681SAndroid Build Coastguard Worker return parsePKHImm(O, "asr", 1, 32);
337*9880d681SAndroid Build Coastguard Worker }
338*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseSetEndImm(OperandVector &);
339*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseShifterImm(OperandVector &);
340*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseRotImm(OperandVector &);
341*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseModImm(OperandVector &);
342*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseBitfield(OperandVector &);
343*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parsePostIdxReg(OperandVector &);
344*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseAM3Offset(OperandVector &);
345*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseFPImm(OperandVector &);
346*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseVectorList(OperandVector &);
347*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index,
348*9880d681SAndroid Build Coastguard Worker SMLoc &EndLoc);
349*9880d681SAndroid Build Coastguard Worker
350*9880d681SAndroid Build Coastguard Worker // Asm Match Converter Methods
351*9880d681SAndroid Build Coastguard Worker void cvtThumbMultiply(MCInst &Inst, const OperandVector &);
352*9880d681SAndroid Build Coastguard Worker void cvtThumbBranches(MCInst &Inst, const OperandVector &);
353*9880d681SAndroid Build Coastguard Worker
354*9880d681SAndroid Build Coastguard Worker bool validateInstruction(MCInst &Inst, const OperandVector &Ops);
355*9880d681SAndroid Build Coastguard Worker bool processInstruction(MCInst &Inst, const OperandVector &Ops, MCStreamer &Out);
356*9880d681SAndroid Build Coastguard Worker bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands);
357*9880d681SAndroid Build Coastguard Worker bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands);
358*9880d681SAndroid Build Coastguard Worker
359*9880d681SAndroid Build Coastguard Worker public:
360*9880d681SAndroid Build Coastguard Worker enum ARMMatchResultTy {
361*9880d681SAndroid Build Coastguard Worker Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
362*9880d681SAndroid Build Coastguard Worker Match_RequiresNotITBlock,
363*9880d681SAndroid Build Coastguard Worker Match_RequiresV6,
364*9880d681SAndroid Build Coastguard Worker Match_RequiresThumb2,
365*9880d681SAndroid Build Coastguard Worker Match_RequiresV8,
366*9880d681SAndroid Build Coastguard Worker #define GET_OPERAND_DIAGNOSTIC_TYPES
367*9880d681SAndroid Build Coastguard Worker #include "ARMGenAsmMatcher.inc"
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker };
370*9880d681SAndroid Build Coastguard Worker
ARMAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)371*9880d681SAndroid Build Coastguard Worker ARMAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
372*9880d681SAndroid Build Coastguard Worker const MCInstrInfo &MII, const MCTargetOptions &Options)
373*9880d681SAndroid Build Coastguard Worker : MCTargetAsmParser(Options, STI), MII(MII), UC(Parser) {
374*9880d681SAndroid Build Coastguard Worker MCAsmParserExtension::Initialize(Parser);
375*9880d681SAndroid Build Coastguard Worker
376*9880d681SAndroid Build Coastguard Worker // Cache the MCRegisterInfo.
377*9880d681SAndroid Build Coastguard Worker MRI = getContext().getRegisterInfo();
378*9880d681SAndroid Build Coastguard Worker
379*9880d681SAndroid Build Coastguard Worker // Initialize the set of available features.
380*9880d681SAndroid Build Coastguard Worker setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
381*9880d681SAndroid Build Coastguard Worker
382*9880d681SAndroid Build Coastguard Worker // Not in an ITBlock to start with.
383*9880d681SAndroid Build Coastguard Worker ITState.CurPosition = ~0U;
384*9880d681SAndroid Build Coastguard Worker
385*9880d681SAndroid Build Coastguard Worker NextSymbolIsThumb = false;
386*9880d681SAndroid Build Coastguard Worker }
387*9880d681SAndroid Build Coastguard Worker
388*9880d681SAndroid Build Coastguard Worker // Implementation of the MCTargetAsmParser interface:
389*9880d681SAndroid Build Coastguard Worker bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
390*9880d681SAndroid Build Coastguard Worker bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
391*9880d681SAndroid Build Coastguard Worker SMLoc NameLoc, OperandVector &Operands) override;
392*9880d681SAndroid Build Coastguard Worker bool ParseDirective(AsmToken DirectiveID) override;
393*9880d681SAndroid Build Coastguard Worker
394*9880d681SAndroid Build Coastguard Worker unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
395*9880d681SAndroid Build Coastguard Worker unsigned Kind) override;
396*9880d681SAndroid Build Coastguard Worker unsigned checkTargetMatchPredicate(MCInst &Inst) override;
397*9880d681SAndroid Build Coastguard Worker
398*9880d681SAndroid Build Coastguard Worker bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
399*9880d681SAndroid Build Coastguard Worker OperandVector &Operands, MCStreamer &Out,
400*9880d681SAndroid Build Coastguard Worker uint64_t &ErrorInfo,
401*9880d681SAndroid Build Coastguard Worker bool MatchingInlineAsm) override;
402*9880d681SAndroid Build Coastguard Worker void onLabelParsed(MCSymbol *Symbol) override;
403*9880d681SAndroid Build Coastguard Worker };
404*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
405*9880d681SAndroid Build Coastguard Worker
406*9880d681SAndroid Build Coastguard Worker namespace {
407*9880d681SAndroid Build Coastguard Worker
408*9880d681SAndroid Build Coastguard Worker /// ARMOperand - Instances of this class represent a parsed ARM machine
409*9880d681SAndroid Build Coastguard Worker /// operand.
410*9880d681SAndroid Build Coastguard Worker class ARMOperand : public MCParsedAsmOperand {
411*9880d681SAndroid Build Coastguard Worker enum KindTy {
412*9880d681SAndroid Build Coastguard Worker k_CondCode,
413*9880d681SAndroid Build Coastguard Worker k_CCOut,
414*9880d681SAndroid Build Coastguard Worker k_ITCondMask,
415*9880d681SAndroid Build Coastguard Worker k_CoprocNum,
416*9880d681SAndroid Build Coastguard Worker k_CoprocReg,
417*9880d681SAndroid Build Coastguard Worker k_CoprocOption,
418*9880d681SAndroid Build Coastguard Worker k_Immediate,
419*9880d681SAndroid Build Coastguard Worker k_MemBarrierOpt,
420*9880d681SAndroid Build Coastguard Worker k_InstSyncBarrierOpt,
421*9880d681SAndroid Build Coastguard Worker k_Memory,
422*9880d681SAndroid Build Coastguard Worker k_PostIndexRegister,
423*9880d681SAndroid Build Coastguard Worker k_MSRMask,
424*9880d681SAndroid Build Coastguard Worker k_BankedReg,
425*9880d681SAndroid Build Coastguard Worker k_ProcIFlags,
426*9880d681SAndroid Build Coastguard Worker k_VectorIndex,
427*9880d681SAndroid Build Coastguard Worker k_Register,
428*9880d681SAndroid Build Coastguard Worker k_RegisterList,
429*9880d681SAndroid Build Coastguard Worker k_DPRRegisterList,
430*9880d681SAndroid Build Coastguard Worker k_SPRRegisterList,
431*9880d681SAndroid Build Coastguard Worker k_VectorList,
432*9880d681SAndroid Build Coastguard Worker k_VectorListAllLanes,
433*9880d681SAndroid Build Coastguard Worker k_VectorListIndexed,
434*9880d681SAndroid Build Coastguard Worker k_ShiftedRegister,
435*9880d681SAndroid Build Coastguard Worker k_ShiftedImmediate,
436*9880d681SAndroid Build Coastguard Worker k_ShifterImmediate,
437*9880d681SAndroid Build Coastguard Worker k_RotateImmediate,
438*9880d681SAndroid Build Coastguard Worker k_ModifiedImmediate,
439*9880d681SAndroid Build Coastguard Worker k_ConstantPoolImmediate,
440*9880d681SAndroid Build Coastguard Worker k_BitfieldDescriptor,
441*9880d681SAndroid Build Coastguard Worker k_Token,
442*9880d681SAndroid Build Coastguard Worker } Kind;
443*9880d681SAndroid Build Coastguard Worker
444*9880d681SAndroid Build Coastguard Worker SMLoc StartLoc, EndLoc, AlignmentLoc;
445*9880d681SAndroid Build Coastguard Worker SmallVector<unsigned, 8> Registers;
446*9880d681SAndroid Build Coastguard Worker
447*9880d681SAndroid Build Coastguard Worker struct CCOp {
448*9880d681SAndroid Build Coastguard Worker ARMCC::CondCodes Val;
449*9880d681SAndroid Build Coastguard Worker };
450*9880d681SAndroid Build Coastguard Worker
451*9880d681SAndroid Build Coastguard Worker struct CopOp {
452*9880d681SAndroid Build Coastguard Worker unsigned Val;
453*9880d681SAndroid Build Coastguard Worker };
454*9880d681SAndroid Build Coastguard Worker
455*9880d681SAndroid Build Coastguard Worker struct CoprocOptionOp {
456*9880d681SAndroid Build Coastguard Worker unsigned Val;
457*9880d681SAndroid Build Coastguard Worker };
458*9880d681SAndroid Build Coastguard Worker
459*9880d681SAndroid Build Coastguard Worker struct ITMaskOp {
460*9880d681SAndroid Build Coastguard Worker unsigned Mask:4;
461*9880d681SAndroid Build Coastguard Worker };
462*9880d681SAndroid Build Coastguard Worker
463*9880d681SAndroid Build Coastguard Worker struct MBOptOp {
464*9880d681SAndroid Build Coastguard Worker ARM_MB::MemBOpt Val;
465*9880d681SAndroid Build Coastguard Worker };
466*9880d681SAndroid Build Coastguard Worker
467*9880d681SAndroid Build Coastguard Worker struct ISBOptOp {
468*9880d681SAndroid Build Coastguard Worker ARM_ISB::InstSyncBOpt Val;
469*9880d681SAndroid Build Coastguard Worker };
470*9880d681SAndroid Build Coastguard Worker
471*9880d681SAndroid Build Coastguard Worker struct IFlagsOp {
472*9880d681SAndroid Build Coastguard Worker ARM_PROC::IFlags Val;
473*9880d681SAndroid Build Coastguard Worker };
474*9880d681SAndroid Build Coastguard Worker
475*9880d681SAndroid Build Coastguard Worker struct MMaskOp {
476*9880d681SAndroid Build Coastguard Worker unsigned Val;
477*9880d681SAndroid Build Coastguard Worker };
478*9880d681SAndroid Build Coastguard Worker
479*9880d681SAndroid Build Coastguard Worker struct BankedRegOp {
480*9880d681SAndroid Build Coastguard Worker unsigned Val;
481*9880d681SAndroid Build Coastguard Worker };
482*9880d681SAndroid Build Coastguard Worker
483*9880d681SAndroid Build Coastguard Worker struct TokOp {
484*9880d681SAndroid Build Coastguard Worker const char *Data;
485*9880d681SAndroid Build Coastguard Worker unsigned Length;
486*9880d681SAndroid Build Coastguard Worker };
487*9880d681SAndroid Build Coastguard Worker
488*9880d681SAndroid Build Coastguard Worker struct RegOp {
489*9880d681SAndroid Build Coastguard Worker unsigned RegNum;
490*9880d681SAndroid Build Coastguard Worker };
491*9880d681SAndroid Build Coastguard Worker
492*9880d681SAndroid Build Coastguard Worker // A vector register list is a sequential list of 1 to 4 registers.
493*9880d681SAndroid Build Coastguard Worker struct VectorListOp {
494*9880d681SAndroid Build Coastguard Worker unsigned RegNum;
495*9880d681SAndroid Build Coastguard Worker unsigned Count;
496*9880d681SAndroid Build Coastguard Worker unsigned LaneIndex;
497*9880d681SAndroid Build Coastguard Worker bool isDoubleSpaced;
498*9880d681SAndroid Build Coastguard Worker };
499*9880d681SAndroid Build Coastguard Worker
500*9880d681SAndroid Build Coastguard Worker struct VectorIndexOp {
501*9880d681SAndroid Build Coastguard Worker unsigned Val;
502*9880d681SAndroid Build Coastguard Worker };
503*9880d681SAndroid Build Coastguard Worker
504*9880d681SAndroid Build Coastguard Worker struct ImmOp {
505*9880d681SAndroid Build Coastguard Worker const MCExpr *Val;
506*9880d681SAndroid Build Coastguard Worker };
507*9880d681SAndroid Build Coastguard Worker
508*9880d681SAndroid Build Coastguard Worker /// Combined record for all forms of ARM address expressions.
509*9880d681SAndroid Build Coastguard Worker struct MemoryOp {
510*9880d681SAndroid Build Coastguard Worker unsigned BaseRegNum;
511*9880d681SAndroid Build Coastguard Worker // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
512*9880d681SAndroid Build Coastguard Worker // was specified.
513*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *OffsetImm; // Offset immediate value
514*9880d681SAndroid Build Coastguard Worker unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
515*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
516*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm; // shift for OffsetReg.
517*9880d681SAndroid Build Coastguard Worker unsigned Alignment; // 0 = no alignment specified
518*9880d681SAndroid Build Coastguard Worker // n = alignment in bytes (2, 4, 8, 16, or 32)
519*9880d681SAndroid Build Coastguard Worker unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
520*9880d681SAndroid Build Coastguard Worker };
521*9880d681SAndroid Build Coastguard Worker
522*9880d681SAndroid Build Coastguard Worker struct PostIdxRegOp {
523*9880d681SAndroid Build Coastguard Worker unsigned RegNum;
524*9880d681SAndroid Build Coastguard Worker bool isAdd;
525*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc ShiftTy;
526*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm;
527*9880d681SAndroid Build Coastguard Worker };
528*9880d681SAndroid Build Coastguard Worker
529*9880d681SAndroid Build Coastguard Worker struct ShifterImmOp {
530*9880d681SAndroid Build Coastguard Worker bool isASR;
531*9880d681SAndroid Build Coastguard Worker unsigned Imm;
532*9880d681SAndroid Build Coastguard Worker };
533*9880d681SAndroid Build Coastguard Worker
534*9880d681SAndroid Build Coastguard Worker struct RegShiftedRegOp {
535*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc ShiftTy;
536*9880d681SAndroid Build Coastguard Worker unsigned SrcReg;
537*9880d681SAndroid Build Coastguard Worker unsigned ShiftReg;
538*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm;
539*9880d681SAndroid Build Coastguard Worker };
540*9880d681SAndroid Build Coastguard Worker
541*9880d681SAndroid Build Coastguard Worker struct RegShiftedImmOp {
542*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc ShiftTy;
543*9880d681SAndroid Build Coastguard Worker unsigned SrcReg;
544*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm;
545*9880d681SAndroid Build Coastguard Worker };
546*9880d681SAndroid Build Coastguard Worker
547*9880d681SAndroid Build Coastguard Worker struct RotImmOp {
548*9880d681SAndroid Build Coastguard Worker unsigned Imm;
549*9880d681SAndroid Build Coastguard Worker };
550*9880d681SAndroid Build Coastguard Worker
551*9880d681SAndroid Build Coastguard Worker struct ModImmOp {
552*9880d681SAndroid Build Coastguard Worker unsigned Bits;
553*9880d681SAndroid Build Coastguard Worker unsigned Rot;
554*9880d681SAndroid Build Coastguard Worker };
555*9880d681SAndroid Build Coastguard Worker
556*9880d681SAndroid Build Coastguard Worker struct BitfieldOp {
557*9880d681SAndroid Build Coastguard Worker unsigned LSB;
558*9880d681SAndroid Build Coastguard Worker unsigned Width;
559*9880d681SAndroid Build Coastguard Worker };
560*9880d681SAndroid Build Coastguard Worker
561*9880d681SAndroid Build Coastguard Worker union {
562*9880d681SAndroid Build Coastguard Worker struct CCOp CC;
563*9880d681SAndroid Build Coastguard Worker struct CopOp Cop;
564*9880d681SAndroid Build Coastguard Worker struct CoprocOptionOp CoprocOption;
565*9880d681SAndroid Build Coastguard Worker struct MBOptOp MBOpt;
566*9880d681SAndroid Build Coastguard Worker struct ISBOptOp ISBOpt;
567*9880d681SAndroid Build Coastguard Worker struct ITMaskOp ITMask;
568*9880d681SAndroid Build Coastguard Worker struct IFlagsOp IFlags;
569*9880d681SAndroid Build Coastguard Worker struct MMaskOp MMask;
570*9880d681SAndroid Build Coastguard Worker struct BankedRegOp BankedReg;
571*9880d681SAndroid Build Coastguard Worker struct TokOp Tok;
572*9880d681SAndroid Build Coastguard Worker struct RegOp Reg;
573*9880d681SAndroid Build Coastguard Worker struct VectorListOp VectorList;
574*9880d681SAndroid Build Coastguard Worker struct VectorIndexOp VectorIndex;
575*9880d681SAndroid Build Coastguard Worker struct ImmOp Imm;
576*9880d681SAndroid Build Coastguard Worker struct MemoryOp Memory;
577*9880d681SAndroid Build Coastguard Worker struct PostIdxRegOp PostIdxReg;
578*9880d681SAndroid Build Coastguard Worker struct ShifterImmOp ShifterImm;
579*9880d681SAndroid Build Coastguard Worker struct RegShiftedRegOp RegShiftedReg;
580*9880d681SAndroid Build Coastguard Worker struct RegShiftedImmOp RegShiftedImm;
581*9880d681SAndroid Build Coastguard Worker struct RotImmOp RotImm;
582*9880d681SAndroid Build Coastguard Worker struct ModImmOp ModImm;
583*9880d681SAndroid Build Coastguard Worker struct BitfieldOp Bitfield;
584*9880d681SAndroid Build Coastguard Worker };
585*9880d681SAndroid Build Coastguard Worker
586*9880d681SAndroid Build Coastguard Worker public:
ARMOperand(KindTy K)587*9880d681SAndroid Build Coastguard Worker ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
588*9880d681SAndroid Build Coastguard Worker
589*9880d681SAndroid Build Coastguard Worker /// getStartLoc - Get the location of the first token of this operand.
getStartLoc() const590*9880d681SAndroid Build Coastguard Worker SMLoc getStartLoc() const override { return StartLoc; }
591*9880d681SAndroid Build Coastguard Worker /// getEndLoc - Get the location of the last token of this operand.
getEndLoc() const592*9880d681SAndroid Build Coastguard Worker SMLoc getEndLoc() const override { return EndLoc; }
593*9880d681SAndroid Build Coastguard Worker /// getLocRange - Get the range between the first and last token of this
594*9880d681SAndroid Build Coastguard Worker /// operand.
getLocRange() const595*9880d681SAndroid Build Coastguard Worker SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
596*9880d681SAndroid Build Coastguard Worker
597*9880d681SAndroid Build Coastguard Worker /// getAlignmentLoc - Get the location of the Alignment token of this operand.
getAlignmentLoc() const598*9880d681SAndroid Build Coastguard Worker SMLoc getAlignmentLoc() const {
599*9880d681SAndroid Build Coastguard Worker assert(Kind == k_Memory && "Invalid access!");
600*9880d681SAndroid Build Coastguard Worker return AlignmentLoc;
601*9880d681SAndroid Build Coastguard Worker }
602*9880d681SAndroid Build Coastguard Worker
getCondCode() const603*9880d681SAndroid Build Coastguard Worker ARMCC::CondCodes getCondCode() const {
604*9880d681SAndroid Build Coastguard Worker assert(Kind == k_CondCode && "Invalid access!");
605*9880d681SAndroid Build Coastguard Worker return CC.Val;
606*9880d681SAndroid Build Coastguard Worker }
607*9880d681SAndroid Build Coastguard Worker
getCoproc() const608*9880d681SAndroid Build Coastguard Worker unsigned getCoproc() const {
609*9880d681SAndroid Build Coastguard Worker assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
610*9880d681SAndroid Build Coastguard Worker return Cop.Val;
611*9880d681SAndroid Build Coastguard Worker }
612*9880d681SAndroid Build Coastguard Worker
getToken() const613*9880d681SAndroid Build Coastguard Worker StringRef getToken() const {
614*9880d681SAndroid Build Coastguard Worker assert(Kind == k_Token && "Invalid access!");
615*9880d681SAndroid Build Coastguard Worker return StringRef(Tok.Data, Tok.Length);
616*9880d681SAndroid Build Coastguard Worker }
617*9880d681SAndroid Build Coastguard Worker
getReg() const618*9880d681SAndroid Build Coastguard Worker unsigned getReg() const override {
619*9880d681SAndroid Build Coastguard Worker assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
620*9880d681SAndroid Build Coastguard Worker return Reg.RegNum;
621*9880d681SAndroid Build Coastguard Worker }
622*9880d681SAndroid Build Coastguard Worker
getRegList() const623*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<unsigned> &getRegList() const {
624*9880d681SAndroid Build Coastguard Worker assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
625*9880d681SAndroid Build Coastguard Worker Kind == k_SPRRegisterList) && "Invalid access!");
626*9880d681SAndroid Build Coastguard Worker return Registers;
627*9880d681SAndroid Build Coastguard Worker }
628*9880d681SAndroid Build Coastguard Worker
getImm() const629*9880d681SAndroid Build Coastguard Worker const MCExpr *getImm() const {
630*9880d681SAndroid Build Coastguard Worker assert(isImm() && "Invalid access!");
631*9880d681SAndroid Build Coastguard Worker return Imm.Val;
632*9880d681SAndroid Build Coastguard Worker }
633*9880d681SAndroid Build Coastguard Worker
getConstantPoolImm() const634*9880d681SAndroid Build Coastguard Worker const MCExpr *getConstantPoolImm() const {
635*9880d681SAndroid Build Coastguard Worker assert(isConstantPoolImm() && "Invalid access!");
636*9880d681SAndroid Build Coastguard Worker return Imm.Val;
637*9880d681SAndroid Build Coastguard Worker }
638*9880d681SAndroid Build Coastguard Worker
getVectorIndex() const639*9880d681SAndroid Build Coastguard Worker unsigned getVectorIndex() const {
640*9880d681SAndroid Build Coastguard Worker assert(Kind == k_VectorIndex && "Invalid access!");
641*9880d681SAndroid Build Coastguard Worker return VectorIndex.Val;
642*9880d681SAndroid Build Coastguard Worker }
643*9880d681SAndroid Build Coastguard Worker
getMemBarrierOpt() const644*9880d681SAndroid Build Coastguard Worker ARM_MB::MemBOpt getMemBarrierOpt() const {
645*9880d681SAndroid Build Coastguard Worker assert(Kind == k_MemBarrierOpt && "Invalid access!");
646*9880d681SAndroid Build Coastguard Worker return MBOpt.Val;
647*9880d681SAndroid Build Coastguard Worker }
648*9880d681SAndroid Build Coastguard Worker
getInstSyncBarrierOpt() const649*9880d681SAndroid Build Coastguard Worker ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const {
650*9880d681SAndroid Build Coastguard Worker assert(Kind == k_InstSyncBarrierOpt && "Invalid access!");
651*9880d681SAndroid Build Coastguard Worker return ISBOpt.Val;
652*9880d681SAndroid Build Coastguard Worker }
653*9880d681SAndroid Build Coastguard Worker
getProcIFlags() const654*9880d681SAndroid Build Coastguard Worker ARM_PROC::IFlags getProcIFlags() const {
655*9880d681SAndroid Build Coastguard Worker assert(Kind == k_ProcIFlags && "Invalid access!");
656*9880d681SAndroid Build Coastguard Worker return IFlags.Val;
657*9880d681SAndroid Build Coastguard Worker }
658*9880d681SAndroid Build Coastguard Worker
getMSRMask() const659*9880d681SAndroid Build Coastguard Worker unsigned getMSRMask() const {
660*9880d681SAndroid Build Coastguard Worker assert(Kind == k_MSRMask && "Invalid access!");
661*9880d681SAndroid Build Coastguard Worker return MMask.Val;
662*9880d681SAndroid Build Coastguard Worker }
663*9880d681SAndroid Build Coastguard Worker
getBankedReg() const664*9880d681SAndroid Build Coastguard Worker unsigned getBankedReg() const {
665*9880d681SAndroid Build Coastguard Worker assert(Kind == k_BankedReg && "Invalid access!");
666*9880d681SAndroid Build Coastguard Worker return BankedReg.Val;
667*9880d681SAndroid Build Coastguard Worker }
668*9880d681SAndroid Build Coastguard Worker
isCoprocNum() const669*9880d681SAndroid Build Coastguard Worker bool isCoprocNum() const { return Kind == k_CoprocNum; }
isCoprocReg() const670*9880d681SAndroid Build Coastguard Worker bool isCoprocReg() const { return Kind == k_CoprocReg; }
isCoprocOption() const671*9880d681SAndroid Build Coastguard Worker bool isCoprocOption() const { return Kind == k_CoprocOption; }
isCondCode() const672*9880d681SAndroid Build Coastguard Worker bool isCondCode() const { return Kind == k_CondCode; }
isCCOut() const673*9880d681SAndroid Build Coastguard Worker bool isCCOut() const { return Kind == k_CCOut; }
isITMask() const674*9880d681SAndroid Build Coastguard Worker bool isITMask() const { return Kind == k_ITCondMask; }
isITCondCode() const675*9880d681SAndroid Build Coastguard Worker bool isITCondCode() const { return Kind == k_CondCode; }
isImm() const676*9880d681SAndroid Build Coastguard Worker bool isImm() const override {
677*9880d681SAndroid Build Coastguard Worker return Kind == k_Immediate;
678*9880d681SAndroid Build Coastguard Worker }
679*9880d681SAndroid Build Coastguard Worker
isARMBranchTarget() const680*9880d681SAndroid Build Coastguard Worker bool isARMBranchTarget() const {
681*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
682*9880d681SAndroid Build Coastguard Worker
683*9880d681SAndroid Build Coastguard Worker if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()))
684*9880d681SAndroid Build Coastguard Worker return CE->getValue() % 4 == 0;
685*9880d681SAndroid Build Coastguard Worker return true;
686*9880d681SAndroid Build Coastguard Worker }
687*9880d681SAndroid Build Coastguard Worker
688*9880d681SAndroid Build Coastguard Worker
isThumbBranchTarget() const689*9880d681SAndroid Build Coastguard Worker bool isThumbBranchTarget() const {
690*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
691*9880d681SAndroid Build Coastguard Worker
692*9880d681SAndroid Build Coastguard Worker if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()))
693*9880d681SAndroid Build Coastguard Worker return CE->getValue() % 2 == 0;
694*9880d681SAndroid Build Coastguard Worker return true;
695*9880d681SAndroid Build Coastguard Worker }
696*9880d681SAndroid Build Coastguard Worker
697*9880d681SAndroid Build Coastguard Worker // checks whether this operand is an unsigned offset which fits is a field
698*9880d681SAndroid Build Coastguard Worker // of specified width and scaled by a specific number of bits
699*9880d681SAndroid Build Coastguard Worker template<unsigned width, unsigned scale>
isUnsignedOffset() const700*9880d681SAndroid Build Coastguard Worker bool isUnsignedOffset() const {
701*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
702*9880d681SAndroid Build Coastguard Worker if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
703*9880d681SAndroid Build Coastguard Worker if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
704*9880d681SAndroid Build Coastguard Worker int64_t Val = CE->getValue();
705*9880d681SAndroid Build Coastguard Worker int64_t Align = 1LL << scale;
706*9880d681SAndroid Build Coastguard Worker int64_t Max = Align * ((1LL << width) - 1);
707*9880d681SAndroid Build Coastguard Worker return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max);
708*9880d681SAndroid Build Coastguard Worker }
709*9880d681SAndroid Build Coastguard Worker return false;
710*9880d681SAndroid Build Coastguard Worker }
711*9880d681SAndroid Build Coastguard Worker // checks whether this operand is an signed offset which fits is a field
712*9880d681SAndroid Build Coastguard Worker // of specified width and scaled by a specific number of bits
713*9880d681SAndroid Build Coastguard Worker template<unsigned width, unsigned scale>
isSignedOffset() const714*9880d681SAndroid Build Coastguard Worker bool isSignedOffset() const {
715*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
716*9880d681SAndroid Build Coastguard Worker if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
717*9880d681SAndroid Build Coastguard Worker if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
718*9880d681SAndroid Build Coastguard Worker int64_t Val = CE->getValue();
719*9880d681SAndroid Build Coastguard Worker int64_t Align = 1LL << scale;
720*9880d681SAndroid Build Coastguard Worker int64_t Max = Align * ((1LL << (width-1)) - 1);
721*9880d681SAndroid Build Coastguard Worker int64_t Min = -Align * (1LL << (width-1));
722*9880d681SAndroid Build Coastguard Worker return ((Val % Align) == 0) && (Val >= Min) && (Val <= Max);
723*9880d681SAndroid Build Coastguard Worker }
724*9880d681SAndroid Build Coastguard Worker return false;
725*9880d681SAndroid Build Coastguard Worker }
726*9880d681SAndroid Build Coastguard Worker
727*9880d681SAndroid Build Coastguard Worker // checks whether this operand is a memory operand computed as an offset
728*9880d681SAndroid Build Coastguard Worker // applied to PC. the offset may have 8 bits of magnitude and is represented
729*9880d681SAndroid Build Coastguard Worker // with two bits of shift. textually it may be either [pc, #imm], #imm or
730*9880d681SAndroid Build Coastguard Worker // relocable expression...
isThumbMemPC() const731*9880d681SAndroid Build Coastguard Worker bool isThumbMemPC() const {
732*9880d681SAndroid Build Coastguard Worker int64_t Val = 0;
733*9880d681SAndroid Build Coastguard Worker if (isImm()) {
734*9880d681SAndroid Build Coastguard Worker if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
735*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val);
736*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
737*9880d681SAndroid Build Coastguard Worker Val = CE->getValue();
738*9880d681SAndroid Build Coastguard Worker }
739*9880d681SAndroid Build Coastguard Worker else if (isMem()) {
740*9880d681SAndroid Build Coastguard Worker if(!Memory.OffsetImm || Memory.OffsetRegNum) return false;
741*9880d681SAndroid Build Coastguard Worker if(Memory.BaseRegNum != ARM::PC) return false;
742*9880d681SAndroid Build Coastguard Worker Val = Memory.OffsetImm->getValue();
743*9880d681SAndroid Build Coastguard Worker }
744*9880d681SAndroid Build Coastguard Worker else return false;
745*9880d681SAndroid Build Coastguard Worker return ((Val % 4) == 0) && (Val >= 0) && (Val <= 1020);
746*9880d681SAndroid Build Coastguard Worker }
isFPImm() const747*9880d681SAndroid Build Coastguard Worker bool isFPImm() const {
748*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
749*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
750*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
751*9880d681SAndroid Build Coastguard Worker int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
752*9880d681SAndroid Build Coastguard Worker return Val != -1;
753*9880d681SAndroid Build Coastguard Worker }
isFBits16() const754*9880d681SAndroid Build Coastguard Worker bool isFBits16() const {
755*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
756*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
757*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
758*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
759*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value <= 16;
760*9880d681SAndroid Build Coastguard Worker }
isFBits32() const761*9880d681SAndroid Build Coastguard Worker bool isFBits32() const {
762*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
763*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
765*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
766*9880d681SAndroid Build Coastguard Worker return Value >= 1 && Value <= 32;
767*9880d681SAndroid Build Coastguard Worker }
isImm8s4() const768*9880d681SAndroid Build Coastguard Worker bool isImm8s4() const {
769*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
770*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
771*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
772*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
773*9880d681SAndroid Build Coastguard Worker return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
774*9880d681SAndroid Build Coastguard Worker }
isImm0_1020s4() const775*9880d681SAndroid Build Coastguard Worker bool isImm0_1020s4() const {
776*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
777*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
778*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
779*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
780*9880d681SAndroid Build Coastguard Worker return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
781*9880d681SAndroid Build Coastguard Worker }
isImm0_508s4() const782*9880d681SAndroid Build Coastguard Worker bool isImm0_508s4() const {
783*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
784*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
785*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
786*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
787*9880d681SAndroid Build Coastguard Worker return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
788*9880d681SAndroid Build Coastguard Worker }
isImm0_508s4Neg() const789*9880d681SAndroid Build Coastguard Worker bool isImm0_508s4Neg() const {
790*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
791*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
792*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
793*9880d681SAndroid Build Coastguard Worker int64_t Value = -CE->getValue();
794*9880d681SAndroid Build Coastguard Worker // explicitly exclude zero. we want that to use the normal 0_508 version.
795*9880d681SAndroid Build Coastguard Worker return ((Value & 3) == 0) && Value > 0 && Value <= 508;
796*9880d681SAndroid Build Coastguard Worker }
isImm0_239() const797*9880d681SAndroid Build Coastguard Worker bool isImm0_239() const {
798*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
799*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
800*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
801*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
802*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 240;
803*9880d681SAndroid Build Coastguard Worker }
isImm0_255() const804*9880d681SAndroid Build Coastguard Worker bool isImm0_255() const {
805*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
806*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
807*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
808*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
809*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 256;
810*9880d681SAndroid Build Coastguard Worker }
isImm0_4095() const811*9880d681SAndroid Build Coastguard Worker bool isImm0_4095() const {
812*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
813*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
814*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
815*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
816*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 4096;
817*9880d681SAndroid Build Coastguard Worker }
isImm0_4095Neg() const818*9880d681SAndroid Build Coastguard Worker bool isImm0_4095Neg() const {
819*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
820*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
821*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
822*9880d681SAndroid Build Coastguard Worker int64_t Value = -CE->getValue();
823*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value < 4096;
824*9880d681SAndroid Build Coastguard Worker }
isImm0_1() const825*9880d681SAndroid Build Coastguard Worker bool isImm0_1() const {
826*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
827*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
828*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
829*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
830*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 2;
831*9880d681SAndroid Build Coastguard Worker }
isImm0_3() const832*9880d681SAndroid Build Coastguard Worker bool isImm0_3() const {
833*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
834*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
835*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
836*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
837*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 4;
838*9880d681SAndroid Build Coastguard Worker }
isImm0_7() const839*9880d681SAndroid Build Coastguard Worker bool isImm0_7() const {
840*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
841*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
842*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
843*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
844*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 8;
845*9880d681SAndroid Build Coastguard Worker }
isImm0_15() const846*9880d681SAndroid Build Coastguard Worker bool isImm0_15() const {
847*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
848*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
849*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
850*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
851*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 16;
852*9880d681SAndroid Build Coastguard Worker }
isImm0_31() const853*9880d681SAndroid Build Coastguard Worker bool isImm0_31() const {
854*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
855*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
856*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
857*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
858*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 32;
859*9880d681SAndroid Build Coastguard Worker }
isImm0_63() const860*9880d681SAndroid Build Coastguard Worker bool isImm0_63() const {
861*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
862*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
863*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
864*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
865*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 64;
866*9880d681SAndroid Build Coastguard Worker }
isImm8() const867*9880d681SAndroid Build Coastguard Worker bool isImm8() const {
868*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
869*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
870*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
871*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
872*9880d681SAndroid Build Coastguard Worker return Value == 8;
873*9880d681SAndroid Build Coastguard Worker }
isImm16() const874*9880d681SAndroid Build Coastguard Worker bool isImm16() const {
875*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
876*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
877*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
878*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
879*9880d681SAndroid Build Coastguard Worker return Value == 16;
880*9880d681SAndroid Build Coastguard Worker }
isImm32() const881*9880d681SAndroid Build Coastguard Worker bool isImm32() const {
882*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
883*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
884*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
885*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
886*9880d681SAndroid Build Coastguard Worker return Value == 32;
887*9880d681SAndroid Build Coastguard Worker }
isShrImm8() const888*9880d681SAndroid Build Coastguard Worker bool isShrImm8() const {
889*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
890*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
891*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
892*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
893*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value <= 8;
894*9880d681SAndroid Build Coastguard Worker }
isShrImm16() const895*9880d681SAndroid Build Coastguard Worker bool isShrImm16() const {
896*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
897*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
898*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
899*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
900*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value <= 16;
901*9880d681SAndroid Build Coastguard Worker }
isShrImm32() const902*9880d681SAndroid Build Coastguard Worker bool isShrImm32() const {
903*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
904*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
905*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
906*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
907*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value <= 32;
908*9880d681SAndroid Build Coastguard Worker }
isShrImm64() const909*9880d681SAndroid Build Coastguard Worker bool isShrImm64() const {
910*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
911*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
912*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
913*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
914*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value <= 64;
915*9880d681SAndroid Build Coastguard Worker }
isImm1_7() const916*9880d681SAndroid Build Coastguard Worker bool isImm1_7() const {
917*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
918*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
919*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
920*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
921*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value < 8;
922*9880d681SAndroid Build Coastguard Worker }
isImm1_15() const923*9880d681SAndroid Build Coastguard Worker bool isImm1_15() const {
924*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
925*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
926*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
927*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
928*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value < 16;
929*9880d681SAndroid Build Coastguard Worker }
isImm1_31() const930*9880d681SAndroid Build Coastguard Worker bool isImm1_31() const {
931*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
932*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
933*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
934*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
935*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value < 32;
936*9880d681SAndroid Build Coastguard Worker }
isImm1_16() const937*9880d681SAndroid Build Coastguard Worker bool isImm1_16() const {
938*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
939*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
940*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
941*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
942*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value < 17;
943*9880d681SAndroid Build Coastguard Worker }
isImm1_32() const944*9880d681SAndroid Build Coastguard Worker bool isImm1_32() const {
945*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
946*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
947*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
948*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
949*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value < 33;
950*9880d681SAndroid Build Coastguard Worker }
isImm0_32() const951*9880d681SAndroid Build Coastguard Worker bool isImm0_32() const {
952*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
953*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
954*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
955*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
956*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 33;
957*9880d681SAndroid Build Coastguard Worker }
isImm0_65535() const958*9880d681SAndroid Build Coastguard Worker bool isImm0_65535() const {
959*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
960*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
961*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
962*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
963*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 65536;
964*9880d681SAndroid Build Coastguard Worker }
isImm256_65535Expr() const965*9880d681SAndroid Build Coastguard Worker bool isImm256_65535Expr() const {
966*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
967*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
968*9880d681SAndroid Build Coastguard Worker // If it's not a constant expression, it'll generate a fixup and be
969*9880d681SAndroid Build Coastguard Worker // handled later.
970*9880d681SAndroid Build Coastguard Worker if (!CE) return true;
971*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
972*9880d681SAndroid Build Coastguard Worker return Value >= 256 && Value < 65536;
973*9880d681SAndroid Build Coastguard Worker }
isImm0_65535Expr() const974*9880d681SAndroid Build Coastguard Worker bool isImm0_65535Expr() const {
975*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
976*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
977*9880d681SAndroid Build Coastguard Worker // If it's not a constant expression, it'll generate a fixup and be
978*9880d681SAndroid Build Coastguard Worker // handled later.
979*9880d681SAndroid Build Coastguard Worker if (!CE) return true;
980*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
981*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 65536;
982*9880d681SAndroid Build Coastguard Worker }
isImm24bit() const983*9880d681SAndroid Build Coastguard Worker bool isImm24bit() const {
984*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
985*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
986*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
987*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
988*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value <= 0xffffff;
989*9880d681SAndroid Build Coastguard Worker }
isImmThumbSR() const990*9880d681SAndroid Build Coastguard Worker bool isImmThumbSR() const {
991*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
992*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
993*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
994*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
995*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value < 33;
996*9880d681SAndroid Build Coastguard Worker }
isPKHLSLImm() const997*9880d681SAndroid Build Coastguard Worker bool isPKHLSLImm() const {
998*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
999*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1000*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1001*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1002*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 32;
1003*9880d681SAndroid Build Coastguard Worker }
isPKHASRImm() const1004*9880d681SAndroid Build Coastguard Worker bool isPKHASRImm() const {
1005*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1006*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1007*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1008*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1009*9880d681SAndroid Build Coastguard Worker return Value > 0 && Value <= 32;
1010*9880d681SAndroid Build Coastguard Worker }
isAdrLabel() const1011*9880d681SAndroid Build Coastguard Worker bool isAdrLabel() const {
1012*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
1013*9880d681SAndroid Build Coastguard Worker // reference needing a fixup.
1014*9880d681SAndroid Build Coastguard Worker if (isImm() && !isa<MCConstantExpr>(getImm()))
1015*9880d681SAndroid Build Coastguard Worker return true;
1016*9880d681SAndroid Build Coastguard Worker
1017*9880d681SAndroid Build Coastguard Worker // If it is a constant, it must fit into a modified immediate encoding.
1018*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1019*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1020*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1021*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1022*9880d681SAndroid Build Coastguard Worker return (ARM_AM::getSOImmVal(Value) != -1 ||
1023*9880d681SAndroid Build Coastguard Worker ARM_AM::getSOImmVal(-Value) != -1);
1024*9880d681SAndroid Build Coastguard Worker }
isT2SOImm() const1025*9880d681SAndroid Build Coastguard Worker bool isT2SOImm() const {
1026*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1027*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1028*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1029*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1030*9880d681SAndroid Build Coastguard Worker return ARM_AM::getT2SOImmVal(Value) != -1;
1031*9880d681SAndroid Build Coastguard Worker }
isT2SOImmNot() const1032*9880d681SAndroid Build Coastguard Worker bool isT2SOImmNot() const {
1033*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1034*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1035*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1036*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1037*9880d681SAndroid Build Coastguard Worker return ARM_AM::getT2SOImmVal(Value) == -1 &&
1038*9880d681SAndroid Build Coastguard Worker ARM_AM::getT2SOImmVal(~Value) != -1;
1039*9880d681SAndroid Build Coastguard Worker }
isT2SOImmNeg() const1040*9880d681SAndroid Build Coastguard Worker bool isT2SOImmNeg() const {
1041*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1042*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1043*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1044*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1045*9880d681SAndroid Build Coastguard Worker // Only use this when not representable as a plain so_imm.
1046*9880d681SAndroid Build Coastguard Worker return ARM_AM::getT2SOImmVal(Value) == -1 &&
1047*9880d681SAndroid Build Coastguard Worker ARM_AM::getT2SOImmVal(-Value) != -1;
1048*9880d681SAndroid Build Coastguard Worker }
isSetEndImm() const1049*9880d681SAndroid Build Coastguard Worker bool isSetEndImm() const {
1050*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1051*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1052*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1053*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1054*9880d681SAndroid Build Coastguard Worker return Value == 1 || Value == 0;
1055*9880d681SAndroid Build Coastguard Worker }
isReg() const1056*9880d681SAndroid Build Coastguard Worker bool isReg() const override { return Kind == k_Register; }
isRegList() const1057*9880d681SAndroid Build Coastguard Worker bool isRegList() const { return Kind == k_RegisterList; }
isDPRRegList() const1058*9880d681SAndroid Build Coastguard Worker bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
isSPRRegList() const1059*9880d681SAndroid Build Coastguard Worker bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
isToken() const1060*9880d681SAndroid Build Coastguard Worker bool isToken() const override { return Kind == k_Token; }
isMemBarrierOpt() const1061*9880d681SAndroid Build Coastguard Worker bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
isInstSyncBarrierOpt() const1062*9880d681SAndroid Build Coastguard Worker bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; }
isMem() const1063*9880d681SAndroid Build Coastguard Worker bool isMem() const override { return Kind == k_Memory; }
isShifterImm() const1064*9880d681SAndroid Build Coastguard Worker bool isShifterImm() const { return Kind == k_ShifterImmediate; }
isRegShiftedReg() const1065*9880d681SAndroid Build Coastguard Worker bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
isRegShiftedImm() const1066*9880d681SAndroid Build Coastguard Worker bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
isRotImm() const1067*9880d681SAndroid Build Coastguard Worker bool isRotImm() const { return Kind == k_RotateImmediate; }
isModImm() const1068*9880d681SAndroid Build Coastguard Worker bool isModImm() const { return Kind == k_ModifiedImmediate; }
isModImmNot() const1069*9880d681SAndroid Build Coastguard Worker bool isModImmNot() const {
1070*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1071*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1072*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1073*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1074*9880d681SAndroid Build Coastguard Worker return ARM_AM::getSOImmVal(~Value) != -1;
1075*9880d681SAndroid Build Coastguard Worker }
isModImmNeg() const1076*9880d681SAndroid Build Coastguard Worker bool isModImmNeg() const {
1077*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1078*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1079*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1080*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1081*9880d681SAndroid Build Coastguard Worker return ARM_AM::getSOImmVal(Value) == -1 &&
1082*9880d681SAndroid Build Coastguard Worker ARM_AM::getSOImmVal(-Value) != -1;
1083*9880d681SAndroid Build Coastguard Worker }
isConstantPoolImm() const1084*9880d681SAndroid Build Coastguard Worker bool isConstantPoolImm() const { return Kind == k_ConstantPoolImmediate; }
isBitfield() const1085*9880d681SAndroid Build Coastguard Worker bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
isPostIdxRegShifted() const1086*9880d681SAndroid Build Coastguard Worker bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
isPostIdxReg() const1087*9880d681SAndroid Build Coastguard Worker bool isPostIdxReg() const {
1088*9880d681SAndroid Build Coastguard Worker return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
1089*9880d681SAndroid Build Coastguard Worker }
isMemNoOffset(bool alignOK=false,unsigned Alignment=0) const1090*9880d681SAndroid Build Coastguard Worker bool isMemNoOffset(bool alignOK = false, unsigned Alignment = 0) const {
1091*9880d681SAndroid Build Coastguard Worker if (!isMem())
1092*9880d681SAndroid Build Coastguard Worker return false;
1093*9880d681SAndroid Build Coastguard Worker // No offset of any kind.
1094*9880d681SAndroid Build Coastguard Worker return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr &&
1095*9880d681SAndroid Build Coastguard Worker (alignOK || Memory.Alignment == Alignment);
1096*9880d681SAndroid Build Coastguard Worker }
isMemPCRelImm12() const1097*9880d681SAndroid Build Coastguard Worker bool isMemPCRelImm12() const {
1098*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1099*9880d681SAndroid Build Coastguard Worker return false;
1100*9880d681SAndroid Build Coastguard Worker // Base register must be PC.
1101*9880d681SAndroid Build Coastguard Worker if (Memory.BaseRegNum != ARM::PC)
1102*9880d681SAndroid Build Coastguard Worker return false;
1103*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-4095, 4095].
1104*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1105*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1106*9880d681SAndroid Build Coastguard Worker return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
1107*9880d681SAndroid Build Coastguard Worker }
isAlignedMemory() const1108*9880d681SAndroid Build Coastguard Worker bool isAlignedMemory() const {
1109*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(true);
1110*9880d681SAndroid Build Coastguard Worker }
isAlignedMemoryNone() const1111*9880d681SAndroid Build Coastguard Worker bool isAlignedMemoryNone() const {
1112*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1113*9880d681SAndroid Build Coastguard Worker }
isDupAlignedMemoryNone() const1114*9880d681SAndroid Build Coastguard Worker bool isDupAlignedMemoryNone() const {
1115*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1116*9880d681SAndroid Build Coastguard Worker }
isAlignedMemory16() const1117*9880d681SAndroid Build Coastguard Worker bool isAlignedMemory16() const {
1118*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2.
1119*9880d681SAndroid Build Coastguard Worker return true;
1120*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1121*9880d681SAndroid Build Coastguard Worker }
isDupAlignedMemory16() const1122*9880d681SAndroid Build Coastguard Worker bool isDupAlignedMemory16() const {
1123*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2.
1124*9880d681SAndroid Build Coastguard Worker return true;
1125*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1126*9880d681SAndroid Build Coastguard Worker }
isAlignedMemory32() const1127*9880d681SAndroid Build Coastguard Worker bool isAlignedMemory32() const {
1128*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4.
1129*9880d681SAndroid Build Coastguard Worker return true;
1130*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1131*9880d681SAndroid Build Coastguard Worker }
isDupAlignedMemory32() const1132*9880d681SAndroid Build Coastguard Worker bool isDupAlignedMemory32() const {
1133*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4.
1134*9880d681SAndroid Build Coastguard Worker return true;
1135*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1136*9880d681SAndroid Build Coastguard Worker }
isAlignedMemory64() const1137*9880d681SAndroid Build Coastguard Worker bool isAlignedMemory64() const {
1138*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1139*9880d681SAndroid Build Coastguard Worker return true;
1140*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1141*9880d681SAndroid Build Coastguard Worker }
isDupAlignedMemory64() const1142*9880d681SAndroid Build Coastguard Worker bool isDupAlignedMemory64() const {
1143*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1144*9880d681SAndroid Build Coastguard Worker return true;
1145*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1146*9880d681SAndroid Build Coastguard Worker }
isAlignedMemory64or128() const1147*9880d681SAndroid Build Coastguard Worker bool isAlignedMemory64or128() const {
1148*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1149*9880d681SAndroid Build Coastguard Worker return true;
1150*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16.
1151*9880d681SAndroid Build Coastguard Worker return true;
1152*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1153*9880d681SAndroid Build Coastguard Worker }
isDupAlignedMemory64or128() const1154*9880d681SAndroid Build Coastguard Worker bool isDupAlignedMemory64or128() const {
1155*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1156*9880d681SAndroid Build Coastguard Worker return true;
1157*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16.
1158*9880d681SAndroid Build Coastguard Worker return true;
1159*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1160*9880d681SAndroid Build Coastguard Worker }
isAlignedMemory64or128or256() const1161*9880d681SAndroid Build Coastguard Worker bool isAlignedMemory64or128or256() const {
1162*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1163*9880d681SAndroid Build Coastguard Worker return true;
1164*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16.
1165*9880d681SAndroid Build Coastguard Worker return true;
1166*9880d681SAndroid Build Coastguard Worker if (isMemNoOffset(false, 32)) // alignment in bytes for 256-bits is 32.
1167*9880d681SAndroid Build Coastguard Worker return true;
1168*9880d681SAndroid Build Coastguard Worker return isMemNoOffset(false, 0);
1169*9880d681SAndroid Build Coastguard Worker }
isAddrMode2() const1170*9880d681SAndroid Build Coastguard Worker bool isAddrMode2() const {
1171*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.Alignment != 0) return false;
1172*9880d681SAndroid Build Coastguard Worker // Check for register offset.
1173*9880d681SAndroid Build Coastguard Worker if (Memory.OffsetRegNum) return true;
1174*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-4095, 4095].
1175*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1176*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1177*9880d681SAndroid Build Coastguard Worker return Val > -4096 && Val < 4096;
1178*9880d681SAndroid Build Coastguard Worker }
isAM2OffsetImm() const1179*9880d681SAndroid Build Coastguard Worker bool isAM2OffsetImm() const {
1180*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1181*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-4095, 4095].
1182*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1183*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1184*9880d681SAndroid Build Coastguard Worker int64_t Val = CE->getValue();
1185*9880d681SAndroid Build Coastguard Worker return (Val == INT32_MIN) || (Val > -4096 && Val < 4096);
1186*9880d681SAndroid Build Coastguard Worker }
isAddrMode3() const1187*9880d681SAndroid Build Coastguard Worker bool isAddrMode3() const {
1188*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
1189*9880d681SAndroid Build Coastguard Worker // reference needing a fixup. If it is a constant, it's something else
1190*9880d681SAndroid Build Coastguard Worker // and we reject it.
1191*9880d681SAndroid Build Coastguard Worker if (isImm() && !isa<MCConstantExpr>(getImm()))
1192*9880d681SAndroid Build Coastguard Worker return true;
1193*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.Alignment != 0) return false;
1194*9880d681SAndroid Build Coastguard Worker // No shifts are legal for AM3.
1195*9880d681SAndroid Build Coastguard Worker if (Memory.ShiftType != ARM_AM::no_shift) return false;
1196*9880d681SAndroid Build Coastguard Worker // Check for register offset.
1197*9880d681SAndroid Build Coastguard Worker if (Memory.OffsetRegNum) return true;
1198*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-255, 255].
1199*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1200*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1201*9880d681SAndroid Build Coastguard Worker // The #-0 offset is encoded as INT32_MIN, and we have to check
1202*9880d681SAndroid Build Coastguard Worker // for this too.
1203*9880d681SAndroid Build Coastguard Worker return (Val > -256 && Val < 256) || Val == INT32_MIN;
1204*9880d681SAndroid Build Coastguard Worker }
isAM3Offset() const1205*9880d681SAndroid Build Coastguard Worker bool isAM3Offset() const {
1206*9880d681SAndroid Build Coastguard Worker if (Kind != k_Immediate && Kind != k_PostIndexRegister)
1207*9880d681SAndroid Build Coastguard Worker return false;
1208*9880d681SAndroid Build Coastguard Worker if (Kind == k_PostIndexRegister)
1209*9880d681SAndroid Build Coastguard Worker return PostIdxReg.ShiftTy == ARM_AM::no_shift;
1210*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-255, 255].
1211*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1212*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1213*9880d681SAndroid Build Coastguard Worker int64_t Val = CE->getValue();
1214*9880d681SAndroid Build Coastguard Worker // Special case, #-0 is INT32_MIN.
1215*9880d681SAndroid Build Coastguard Worker return (Val > -256 && Val < 256) || Val == INT32_MIN;
1216*9880d681SAndroid Build Coastguard Worker }
isAddrMode5() const1217*9880d681SAndroid Build Coastguard Worker bool isAddrMode5() const {
1218*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
1219*9880d681SAndroid Build Coastguard Worker // reference needing a fixup. If it is a constant, it's something else
1220*9880d681SAndroid Build Coastguard Worker // and we reject it.
1221*9880d681SAndroid Build Coastguard Worker if (isImm() && !isa<MCConstantExpr>(getImm()))
1222*9880d681SAndroid Build Coastguard Worker return true;
1223*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.Alignment != 0) return false;
1224*9880d681SAndroid Build Coastguard Worker // Check for register offset.
1225*9880d681SAndroid Build Coastguard Worker if (Memory.OffsetRegNum) return false;
1226*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-1020, 1020] and a multiple of 4.
1227*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1228*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1229*9880d681SAndroid Build Coastguard Worker return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
1230*9880d681SAndroid Build Coastguard Worker Val == INT32_MIN;
1231*9880d681SAndroid Build Coastguard Worker }
isAddrMode5FP16() const1232*9880d681SAndroid Build Coastguard Worker bool isAddrMode5FP16() const {
1233*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
1234*9880d681SAndroid Build Coastguard Worker // reference needing a fixup. If it is a constant, it's something else
1235*9880d681SAndroid Build Coastguard Worker // and we reject it.
1236*9880d681SAndroid Build Coastguard Worker if (isImm() && !isa<MCConstantExpr>(getImm()))
1237*9880d681SAndroid Build Coastguard Worker return true;
1238*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.Alignment != 0) return false;
1239*9880d681SAndroid Build Coastguard Worker // Check for register offset.
1240*9880d681SAndroid Build Coastguard Worker if (Memory.OffsetRegNum) return false;
1241*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-510, 510] and a multiple of 2.
1242*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1243*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1244*9880d681SAndroid Build Coastguard Worker return (Val >= -510 && Val <= 510 && ((Val & 1) == 0)) || Val == INT32_MIN;
1245*9880d681SAndroid Build Coastguard Worker }
isMemTBB() const1246*9880d681SAndroid Build Coastguard Worker bool isMemTBB() const {
1247*9880d681SAndroid Build Coastguard Worker if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
1248*9880d681SAndroid Build Coastguard Worker Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
1249*9880d681SAndroid Build Coastguard Worker return false;
1250*9880d681SAndroid Build Coastguard Worker return true;
1251*9880d681SAndroid Build Coastguard Worker }
isMemTBH() const1252*9880d681SAndroid Build Coastguard Worker bool isMemTBH() const {
1253*9880d681SAndroid Build Coastguard Worker if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
1254*9880d681SAndroid Build Coastguard Worker Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
1255*9880d681SAndroid Build Coastguard Worker Memory.Alignment != 0 )
1256*9880d681SAndroid Build Coastguard Worker return false;
1257*9880d681SAndroid Build Coastguard Worker return true;
1258*9880d681SAndroid Build Coastguard Worker }
isMemRegOffset() const1259*9880d681SAndroid Build Coastguard Worker bool isMemRegOffset() const {
1260*9880d681SAndroid Build Coastguard Worker if (!isMem() || !Memory.OffsetRegNum || Memory.Alignment != 0)
1261*9880d681SAndroid Build Coastguard Worker return false;
1262*9880d681SAndroid Build Coastguard Worker return true;
1263*9880d681SAndroid Build Coastguard Worker }
isT2MemRegOffset() const1264*9880d681SAndroid Build Coastguard Worker bool isT2MemRegOffset() const {
1265*9880d681SAndroid Build Coastguard Worker if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
1266*9880d681SAndroid Build Coastguard Worker Memory.Alignment != 0 || Memory.BaseRegNum == ARM::PC)
1267*9880d681SAndroid Build Coastguard Worker return false;
1268*9880d681SAndroid Build Coastguard Worker // Only lsl #{0, 1, 2, 3} allowed.
1269*9880d681SAndroid Build Coastguard Worker if (Memory.ShiftType == ARM_AM::no_shift)
1270*9880d681SAndroid Build Coastguard Worker return true;
1271*9880d681SAndroid Build Coastguard Worker if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
1272*9880d681SAndroid Build Coastguard Worker return false;
1273*9880d681SAndroid Build Coastguard Worker return true;
1274*9880d681SAndroid Build Coastguard Worker }
isMemThumbRR() const1275*9880d681SAndroid Build Coastguard Worker bool isMemThumbRR() const {
1276*9880d681SAndroid Build Coastguard Worker // Thumb reg+reg addressing is simple. Just two registers, a base and
1277*9880d681SAndroid Build Coastguard Worker // an offset. No shifts, negations or any other complicating factors.
1278*9880d681SAndroid Build Coastguard Worker if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
1279*9880d681SAndroid Build Coastguard Worker Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
1280*9880d681SAndroid Build Coastguard Worker return false;
1281*9880d681SAndroid Build Coastguard Worker return isARMLowRegister(Memory.BaseRegNum) &&
1282*9880d681SAndroid Build Coastguard Worker (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
1283*9880d681SAndroid Build Coastguard Worker }
isMemThumbRIs4() const1284*9880d681SAndroid Build Coastguard Worker bool isMemThumbRIs4() const {
1285*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 ||
1286*9880d681SAndroid Build Coastguard Worker !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
1287*9880d681SAndroid Build Coastguard Worker return false;
1288*9880d681SAndroid Build Coastguard Worker // Immediate offset, multiple of 4 in range [0, 124].
1289*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1290*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1291*9880d681SAndroid Build Coastguard Worker return Val >= 0 && Val <= 124 && (Val % 4) == 0;
1292*9880d681SAndroid Build Coastguard Worker }
isMemThumbRIs2() const1293*9880d681SAndroid Build Coastguard Worker bool isMemThumbRIs2() const {
1294*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 ||
1295*9880d681SAndroid Build Coastguard Worker !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
1296*9880d681SAndroid Build Coastguard Worker return false;
1297*9880d681SAndroid Build Coastguard Worker // Immediate offset, multiple of 4 in range [0, 62].
1298*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1299*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1300*9880d681SAndroid Build Coastguard Worker return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1301*9880d681SAndroid Build Coastguard Worker }
isMemThumbRIs1() const1302*9880d681SAndroid Build Coastguard Worker bool isMemThumbRIs1() const {
1303*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 ||
1304*9880d681SAndroid Build Coastguard Worker !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
1305*9880d681SAndroid Build Coastguard Worker return false;
1306*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [0, 31].
1307*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1308*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1309*9880d681SAndroid Build Coastguard Worker return Val >= 0 && Val <= 31;
1310*9880d681SAndroid Build Coastguard Worker }
isMemThumbSPI() const1311*9880d681SAndroid Build Coastguard Worker bool isMemThumbSPI() const {
1312*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 ||
1313*9880d681SAndroid Build Coastguard Worker Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
1314*9880d681SAndroid Build Coastguard Worker return false;
1315*9880d681SAndroid Build Coastguard Worker // Immediate offset, multiple of 4 in range [0, 1020].
1316*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1317*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1318*9880d681SAndroid Build Coastguard Worker return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
1319*9880d681SAndroid Build Coastguard Worker }
isMemImm8s4Offset() const1320*9880d681SAndroid Build Coastguard Worker bool isMemImm8s4Offset() const {
1321*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
1322*9880d681SAndroid Build Coastguard Worker // reference needing a fixup. If it is a constant, it's something else
1323*9880d681SAndroid Build Coastguard Worker // and we reject it.
1324*9880d681SAndroid Build Coastguard Worker if (isImm() && !isa<MCConstantExpr>(getImm()))
1325*9880d681SAndroid Build Coastguard Worker return true;
1326*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1327*9880d681SAndroid Build Coastguard Worker return false;
1328*9880d681SAndroid Build Coastguard Worker // Immediate offset a multiple of 4 in range [-1020, 1020].
1329*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1330*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1331*9880d681SAndroid Build Coastguard Worker // Special case, #-0 is INT32_MIN.
1332*9880d681SAndroid Build Coastguard Worker return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || Val == INT32_MIN;
1333*9880d681SAndroid Build Coastguard Worker }
isMemImm0_1020s4Offset() const1334*9880d681SAndroid Build Coastguard Worker bool isMemImm0_1020s4Offset() const {
1335*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1336*9880d681SAndroid Build Coastguard Worker return false;
1337*9880d681SAndroid Build Coastguard Worker // Immediate offset a multiple of 4 in range [0, 1020].
1338*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1339*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1340*9880d681SAndroid Build Coastguard Worker return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1341*9880d681SAndroid Build Coastguard Worker }
isMemImm8Offset() const1342*9880d681SAndroid Build Coastguard Worker bool isMemImm8Offset() const {
1343*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1344*9880d681SAndroid Build Coastguard Worker return false;
1345*9880d681SAndroid Build Coastguard Worker // Base reg of PC isn't allowed for these encodings.
1346*9880d681SAndroid Build Coastguard Worker if (Memory.BaseRegNum == ARM::PC) return false;
1347*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-255, 255].
1348*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1349*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1350*9880d681SAndroid Build Coastguard Worker return (Val == INT32_MIN) || (Val > -256 && Val < 256);
1351*9880d681SAndroid Build Coastguard Worker }
isMemPosImm8Offset() const1352*9880d681SAndroid Build Coastguard Worker bool isMemPosImm8Offset() const {
1353*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1354*9880d681SAndroid Build Coastguard Worker return false;
1355*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [0, 255].
1356*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1357*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1358*9880d681SAndroid Build Coastguard Worker return Val >= 0 && Val < 256;
1359*9880d681SAndroid Build Coastguard Worker }
isMemNegImm8Offset() const1360*9880d681SAndroid Build Coastguard Worker bool isMemNegImm8Offset() const {
1361*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1362*9880d681SAndroid Build Coastguard Worker return false;
1363*9880d681SAndroid Build Coastguard Worker // Base reg of PC isn't allowed for these encodings.
1364*9880d681SAndroid Build Coastguard Worker if (Memory.BaseRegNum == ARM::PC) return false;
1365*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-255, -1].
1366*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return false;
1367*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1368*9880d681SAndroid Build Coastguard Worker return (Val == INT32_MIN) || (Val > -256 && Val < 0);
1369*9880d681SAndroid Build Coastguard Worker }
isMemUImm12Offset() const1370*9880d681SAndroid Build Coastguard Worker bool isMemUImm12Offset() const {
1371*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1372*9880d681SAndroid Build Coastguard Worker return false;
1373*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [0, 4095].
1374*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1375*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1376*9880d681SAndroid Build Coastguard Worker return (Val >= 0 && Val < 4096);
1377*9880d681SAndroid Build Coastguard Worker }
isMemImm12Offset() const1378*9880d681SAndroid Build Coastguard Worker bool isMemImm12Offset() const {
1379*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
1380*9880d681SAndroid Build Coastguard Worker // reference needing a fixup. If it is a constant, it's something else
1381*9880d681SAndroid Build Coastguard Worker // and we reject it.
1382*9880d681SAndroid Build Coastguard Worker
1383*9880d681SAndroid Build Coastguard Worker if (isImm() && !isa<MCConstantExpr>(getImm()))
1384*9880d681SAndroid Build Coastguard Worker return true;
1385*9880d681SAndroid Build Coastguard Worker
1386*9880d681SAndroid Build Coastguard Worker if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1387*9880d681SAndroid Build Coastguard Worker return false;
1388*9880d681SAndroid Build Coastguard Worker // Immediate offset in range [-4095, 4095].
1389*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetImm) return true;
1390*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm->getValue();
1391*9880d681SAndroid Build Coastguard Worker return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
1392*9880d681SAndroid Build Coastguard Worker }
isConstPoolAsmImm() const1393*9880d681SAndroid Build Coastguard Worker bool isConstPoolAsmImm() const {
1394*9880d681SAndroid Build Coastguard Worker // Delay processing of Constant Pool Immediate, this will turn into
1395*9880d681SAndroid Build Coastguard Worker // a constant. Match no other operand
1396*9880d681SAndroid Build Coastguard Worker return (isConstantPoolImm());
1397*9880d681SAndroid Build Coastguard Worker }
isPostIdxImm8() const1398*9880d681SAndroid Build Coastguard Worker bool isPostIdxImm8() const {
1399*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1400*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1401*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1402*9880d681SAndroid Build Coastguard Worker int64_t Val = CE->getValue();
1403*9880d681SAndroid Build Coastguard Worker return (Val > -256 && Val < 256) || (Val == INT32_MIN);
1404*9880d681SAndroid Build Coastguard Worker }
isPostIdxImm8s4() const1405*9880d681SAndroid Build Coastguard Worker bool isPostIdxImm8s4() const {
1406*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1407*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1408*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1409*9880d681SAndroid Build Coastguard Worker int64_t Val = CE->getValue();
1410*9880d681SAndroid Build Coastguard Worker return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1411*9880d681SAndroid Build Coastguard Worker (Val == INT32_MIN);
1412*9880d681SAndroid Build Coastguard Worker }
1413*9880d681SAndroid Build Coastguard Worker
isMSRMask() const1414*9880d681SAndroid Build Coastguard Worker bool isMSRMask() const { return Kind == k_MSRMask; }
isBankedReg() const1415*9880d681SAndroid Build Coastguard Worker bool isBankedReg() const { return Kind == k_BankedReg; }
isProcIFlags() const1416*9880d681SAndroid Build Coastguard Worker bool isProcIFlags() const { return Kind == k_ProcIFlags; }
1417*9880d681SAndroid Build Coastguard Worker
1418*9880d681SAndroid Build Coastguard Worker // NEON operands.
isSingleSpacedVectorList() const1419*9880d681SAndroid Build Coastguard Worker bool isSingleSpacedVectorList() const {
1420*9880d681SAndroid Build Coastguard Worker return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1421*9880d681SAndroid Build Coastguard Worker }
isDoubleSpacedVectorList() const1422*9880d681SAndroid Build Coastguard Worker bool isDoubleSpacedVectorList() const {
1423*9880d681SAndroid Build Coastguard Worker return Kind == k_VectorList && VectorList.isDoubleSpaced;
1424*9880d681SAndroid Build Coastguard Worker }
isVecListOneD() const1425*9880d681SAndroid Build Coastguard Worker bool isVecListOneD() const {
1426*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorList()) return false;
1427*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 1;
1428*9880d681SAndroid Build Coastguard Worker }
1429*9880d681SAndroid Build Coastguard Worker
isVecListDPair() const1430*9880d681SAndroid Build Coastguard Worker bool isVecListDPair() const {
1431*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorList()) return false;
1432*9880d681SAndroid Build Coastguard Worker return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1433*9880d681SAndroid Build Coastguard Worker .contains(VectorList.RegNum));
1434*9880d681SAndroid Build Coastguard Worker }
1435*9880d681SAndroid Build Coastguard Worker
isVecListThreeD() const1436*9880d681SAndroid Build Coastguard Worker bool isVecListThreeD() const {
1437*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorList()) return false;
1438*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 3;
1439*9880d681SAndroid Build Coastguard Worker }
1440*9880d681SAndroid Build Coastguard Worker
isVecListFourD() const1441*9880d681SAndroid Build Coastguard Worker bool isVecListFourD() const {
1442*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorList()) return false;
1443*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 4;
1444*9880d681SAndroid Build Coastguard Worker }
1445*9880d681SAndroid Build Coastguard Worker
isVecListDPairSpaced() const1446*9880d681SAndroid Build Coastguard Worker bool isVecListDPairSpaced() const {
1447*9880d681SAndroid Build Coastguard Worker if (Kind != k_VectorList) return false;
1448*9880d681SAndroid Build Coastguard Worker if (isSingleSpacedVectorList()) return false;
1449*9880d681SAndroid Build Coastguard Worker return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1450*9880d681SAndroid Build Coastguard Worker .contains(VectorList.RegNum));
1451*9880d681SAndroid Build Coastguard Worker }
1452*9880d681SAndroid Build Coastguard Worker
isVecListThreeQ() const1453*9880d681SAndroid Build Coastguard Worker bool isVecListThreeQ() const {
1454*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorList()) return false;
1455*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 3;
1456*9880d681SAndroid Build Coastguard Worker }
1457*9880d681SAndroid Build Coastguard Worker
isVecListFourQ() const1458*9880d681SAndroid Build Coastguard Worker bool isVecListFourQ() const {
1459*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorList()) return false;
1460*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 4;
1461*9880d681SAndroid Build Coastguard Worker }
1462*9880d681SAndroid Build Coastguard Worker
isSingleSpacedVectorAllLanes() const1463*9880d681SAndroid Build Coastguard Worker bool isSingleSpacedVectorAllLanes() const {
1464*9880d681SAndroid Build Coastguard Worker return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1465*9880d681SAndroid Build Coastguard Worker }
isDoubleSpacedVectorAllLanes() const1466*9880d681SAndroid Build Coastguard Worker bool isDoubleSpacedVectorAllLanes() const {
1467*9880d681SAndroid Build Coastguard Worker return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1468*9880d681SAndroid Build Coastguard Worker }
isVecListOneDAllLanes() const1469*9880d681SAndroid Build Coastguard Worker bool isVecListOneDAllLanes() const {
1470*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorAllLanes()) return false;
1471*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 1;
1472*9880d681SAndroid Build Coastguard Worker }
1473*9880d681SAndroid Build Coastguard Worker
isVecListDPairAllLanes() const1474*9880d681SAndroid Build Coastguard Worker bool isVecListDPairAllLanes() const {
1475*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorAllLanes()) return false;
1476*9880d681SAndroid Build Coastguard Worker return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1477*9880d681SAndroid Build Coastguard Worker .contains(VectorList.RegNum));
1478*9880d681SAndroid Build Coastguard Worker }
1479*9880d681SAndroid Build Coastguard Worker
isVecListDPairSpacedAllLanes() const1480*9880d681SAndroid Build Coastguard Worker bool isVecListDPairSpacedAllLanes() const {
1481*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorAllLanes()) return false;
1482*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 2;
1483*9880d681SAndroid Build Coastguard Worker }
1484*9880d681SAndroid Build Coastguard Worker
isVecListThreeDAllLanes() const1485*9880d681SAndroid Build Coastguard Worker bool isVecListThreeDAllLanes() const {
1486*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorAllLanes()) return false;
1487*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 3;
1488*9880d681SAndroid Build Coastguard Worker }
1489*9880d681SAndroid Build Coastguard Worker
isVecListThreeQAllLanes() const1490*9880d681SAndroid Build Coastguard Worker bool isVecListThreeQAllLanes() const {
1491*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorAllLanes()) return false;
1492*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 3;
1493*9880d681SAndroid Build Coastguard Worker }
1494*9880d681SAndroid Build Coastguard Worker
isVecListFourDAllLanes() const1495*9880d681SAndroid Build Coastguard Worker bool isVecListFourDAllLanes() const {
1496*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorAllLanes()) return false;
1497*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 4;
1498*9880d681SAndroid Build Coastguard Worker }
1499*9880d681SAndroid Build Coastguard Worker
isVecListFourQAllLanes() const1500*9880d681SAndroid Build Coastguard Worker bool isVecListFourQAllLanes() const {
1501*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorAllLanes()) return false;
1502*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 4;
1503*9880d681SAndroid Build Coastguard Worker }
1504*9880d681SAndroid Build Coastguard Worker
isSingleSpacedVectorIndexed() const1505*9880d681SAndroid Build Coastguard Worker bool isSingleSpacedVectorIndexed() const {
1506*9880d681SAndroid Build Coastguard Worker return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1507*9880d681SAndroid Build Coastguard Worker }
isDoubleSpacedVectorIndexed() const1508*9880d681SAndroid Build Coastguard Worker bool isDoubleSpacedVectorIndexed() const {
1509*9880d681SAndroid Build Coastguard Worker return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1510*9880d681SAndroid Build Coastguard Worker }
isVecListOneDByteIndexed() const1511*9880d681SAndroid Build Coastguard Worker bool isVecListOneDByteIndexed() const {
1512*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1513*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1514*9880d681SAndroid Build Coastguard Worker }
1515*9880d681SAndroid Build Coastguard Worker
isVecListOneDHWordIndexed() const1516*9880d681SAndroid Build Coastguard Worker bool isVecListOneDHWordIndexed() const {
1517*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1518*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1519*9880d681SAndroid Build Coastguard Worker }
1520*9880d681SAndroid Build Coastguard Worker
isVecListOneDWordIndexed() const1521*9880d681SAndroid Build Coastguard Worker bool isVecListOneDWordIndexed() const {
1522*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1523*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1524*9880d681SAndroid Build Coastguard Worker }
1525*9880d681SAndroid Build Coastguard Worker
isVecListTwoDByteIndexed() const1526*9880d681SAndroid Build Coastguard Worker bool isVecListTwoDByteIndexed() const {
1527*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1528*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1529*9880d681SAndroid Build Coastguard Worker }
1530*9880d681SAndroid Build Coastguard Worker
isVecListTwoDHWordIndexed() const1531*9880d681SAndroid Build Coastguard Worker bool isVecListTwoDHWordIndexed() const {
1532*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1533*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1534*9880d681SAndroid Build Coastguard Worker }
1535*9880d681SAndroid Build Coastguard Worker
isVecListTwoQWordIndexed() const1536*9880d681SAndroid Build Coastguard Worker bool isVecListTwoQWordIndexed() const {
1537*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorIndexed()) return false;
1538*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1539*9880d681SAndroid Build Coastguard Worker }
1540*9880d681SAndroid Build Coastguard Worker
isVecListTwoQHWordIndexed() const1541*9880d681SAndroid Build Coastguard Worker bool isVecListTwoQHWordIndexed() const {
1542*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorIndexed()) return false;
1543*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1544*9880d681SAndroid Build Coastguard Worker }
1545*9880d681SAndroid Build Coastguard Worker
isVecListTwoDWordIndexed() const1546*9880d681SAndroid Build Coastguard Worker bool isVecListTwoDWordIndexed() const {
1547*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1548*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1549*9880d681SAndroid Build Coastguard Worker }
1550*9880d681SAndroid Build Coastguard Worker
isVecListThreeDByteIndexed() const1551*9880d681SAndroid Build Coastguard Worker bool isVecListThreeDByteIndexed() const {
1552*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1553*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1554*9880d681SAndroid Build Coastguard Worker }
1555*9880d681SAndroid Build Coastguard Worker
isVecListThreeDHWordIndexed() const1556*9880d681SAndroid Build Coastguard Worker bool isVecListThreeDHWordIndexed() const {
1557*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1558*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1559*9880d681SAndroid Build Coastguard Worker }
1560*9880d681SAndroid Build Coastguard Worker
isVecListThreeQWordIndexed() const1561*9880d681SAndroid Build Coastguard Worker bool isVecListThreeQWordIndexed() const {
1562*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorIndexed()) return false;
1563*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1564*9880d681SAndroid Build Coastguard Worker }
1565*9880d681SAndroid Build Coastguard Worker
isVecListThreeQHWordIndexed() const1566*9880d681SAndroid Build Coastguard Worker bool isVecListThreeQHWordIndexed() const {
1567*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorIndexed()) return false;
1568*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1569*9880d681SAndroid Build Coastguard Worker }
1570*9880d681SAndroid Build Coastguard Worker
isVecListThreeDWordIndexed() const1571*9880d681SAndroid Build Coastguard Worker bool isVecListThreeDWordIndexed() const {
1572*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1573*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1574*9880d681SAndroid Build Coastguard Worker }
1575*9880d681SAndroid Build Coastguard Worker
isVecListFourDByteIndexed() const1576*9880d681SAndroid Build Coastguard Worker bool isVecListFourDByteIndexed() const {
1577*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1578*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1579*9880d681SAndroid Build Coastguard Worker }
1580*9880d681SAndroid Build Coastguard Worker
isVecListFourDHWordIndexed() const1581*9880d681SAndroid Build Coastguard Worker bool isVecListFourDHWordIndexed() const {
1582*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1583*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1584*9880d681SAndroid Build Coastguard Worker }
1585*9880d681SAndroid Build Coastguard Worker
isVecListFourQWordIndexed() const1586*9880d681SAndroid Build Coastguard Worker bool isVecListFourQWordIndexed() const {
1587*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorIndexed()) return false;
1588*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1589*9880d681SAndroid Build Coastguard Worker }
1590*9880d681SAndroid Build Coastguard Worker
isVecListFourQHWordIndexed() const1591*9880d681SAndroid Build Coastguard Worker bool isVecListFourQHWordIndexed() const {
1592*9880d681SAndroid Build Coastguard Worker if (!isDoubleSpacedVectorIndexed()) return false;
1593*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1594*9880d681SAndroid Build Coastguard Worker }
1595*9880d681SAndroid Build Coastguard Worker
isVecListFourDWordIndexed() const1596*9880d681SAndroid Build Coastguard Worker bool isVecListFourDWordIndexed() const {
1597*9880d681SAndroid Build Coastguard Worker if (!isSingleSpacedVectorIndexed()) return false;
1598*9880d681SAndroid Build Coastguard Worker return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1599*9880d681SAndroid Build Coastguard Worker }
1600*9880d681SAndroid Build Coastguard Worker
isVectorIndex8() const1601*9880d681SAndroid Build Coastguard Worker bool isVectorIndex8() const {
1602*9880d681SAndroid Build Coastguard Worker if (Kind != k_VectorIndex) return false;
1603*9880d681SAndroid Build Coastguard Worker return VectorIndex.Val < 8;
1604*9880d681SAndroid Build Coastguard Worker }
isVectorIndex16() const1605*9880d681SAndroid Build Coastguard Worker bool isVectorIndex16() const {
1606*9880d681SAndroid Build Coastguard Worker if (Kind != k_VectorIndex) return false;
1607*9880d681SAndroid Build Coastguard Worker return VectorIndex.Val < 4;
1608*9880d681SAndroid Build Coastguard Worker }
isVectorIndex32() const1609*9880d681SAndroid Build Coastguard Worker bool isVectorIndex32() const {
1610*9880d681SAndroid Build Coastguard Worker if (Kind != k_VectorIndex) return false;
1611*9880d681SAndroid Build Coastguard Worker return VectorIndex.Val < 2;
1612*9880d681SAndroid Build Coastguard Worker }
1613*9880d681SAndroid Build Coastguard Worker
isNEONi8splat() const1614*9880d681SAndroid Build Coastguard Worker bool isNEONi8splat() const {
1615*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1616*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1617*9880d681SAndroid Build Coastguard Worker // Must be a constant.
1618*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1619*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1620*9880d681SAndroid Build Coastguard Worker // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1621*9880d681SAndroid Build Coastguard Worker // value.
1622*9880d681SAndroid Build Coastguard Worker return Value >= 0 && Value < 256;
1623*9880d681SAndroid Build Coastguard Worker }
1624*9880d681SAndroid Build Coastguard Worker
isNEONi16splat() const1625*9880d681SAndroid Build Coastguard Worker bool isNEONi16splat() const {
1626*9880d681SAndroid Build Coastguard Worker if (isNEONByteReplicate(2))
1627*9880d681SAndroid Build Coastguard Worker return false; // Leave that for bytes replication and forbid by default.
1628*9880d681SAndroid Build Coastguard Worker if (!isImm())
1629*9880d681SAndroid Build Coastguard Worker return false;
1630*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1631*9880d681SAndroid Build Coastguard Worker // Must be a constant.
1632*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1633*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
1634*9880d681SAndroid Build Coastguard Worker return ARM_AM::isNEONi16splat(Value);
1635*9880d681SAndroid Build Coastguard Worker }
1636*9880d681SAndroid Build Coastguard Worker
isNEONi16splatNot() const1637*9880d681SAndroid Build Coastguard Worker bool isNEONi16splatNot() const {
1638*9880d681SAndroid Build Coastguard Worker if (!isImm())
1639*9880d681SAndroid Build Coastguard Worker return false;
1640*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1641*9880d681SAndroid Build Coastguard Worker // Must be a constant.
1642*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1643*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
1644*9880d681SAndroid Build Coastguard Worker return ARM_AM::isNEONi16splat(~Value & 0xffff);
1645*9880d681SAndroid Build Coastguard Worker }
1646*9880d681SAndroid Build Coastguard Worker
isNEONi32splat() const1647*9880d681SAndroid Build Coastguard Worker bool isNEONi32splat() const {
1648*9880d681SAndroid Build Coastguard Worker if (isNEONByteReplicate(4))
1649*9880d681SAndroid Build Coastguard Worker return false; // Leave that for bytes replication and forbid by default.
1650*9880d681SAndroid Build Coastguard Worker if (!isImm())
1651*9880d681SAndroid Build Coastguard Worker return false;
1652*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1653*9880d681SAndroid Build Coastguard Worker // Must be a constant.
1654*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1655*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
1656*9880d681SAndroid Build Coastguard Worker return ARM_AM::isNEONi32splat(Value);
1657*9880d681SAndroid Build Coastguard Worker }
1658*9880d681SAndroid Build Coastguard Worker
isNEONi32splatNot() const1659*9880d681SAndroid Build Coastguard Worker bool isNEONi32splatNot() const {
1660*9880d681SAndroid Build Coastguard Worker if (!isImm())
1661*9880d681SAndroid Build Coastguard Worker return false;
1662*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1663*9880d681SAndroid Build Coastguard Worker // Must be a constant.
1664*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1665*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
1666*9880d681SAndroid Build Coastguard Worker return ARM_AM::isNEONi32splat(~Value);
1667*9880d681SAndroid Build Coastguard Worker }
1668*9880d681SAndroid Build Coastguard Worker
isNEONByteReplicate(unsigned NumBytes) const1669*9880d681SAndroid Build Coastguard Worker bool isNEONByteReplicate(unsigned NumBytes) const {
1670*9880d681SAndroid Build Coastguard Worker if (!isImm())
1671*9880d681SAndroid Build Coastguard Worker return false;
1672*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1673*9880d681SAndroid Build Coastguard Worker // Must be a constant.
1674*9880d681SAndroid Build Coastguard Worker if (!CE)
1675*9880d681SAndroid Build Coastguard Worker return false;
1676*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1677*9880d681SAndroid Build Coastguard Worker if (!Value)
1678*9880d681SAndroid Build Coastguard Worker return false; // Don't bother with zero.
1679*9880d681SAndroid Build Coastguard Worker
1680*9880d681SAndroid Build Coastguard Worker unsigned char B = Value & 0xff;
1681*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1; i < NumBytes; ++i) {
1682*9880d681SAndroid Build Coastguard Worker Value >>= 8;
1683*9880d681SAndroid Build Coastguard Worker if ((Value & 0xff) != B)
1684*9880d681SAndroid Build Coastguard Worker return false;
1685*9880d681SAndroid Build Coastguard Worker }
1686*9880d681SAndroid Build Coastguard Worker return true;
1687*9880d681SAndroid Build Coastguard Worker }
isNEONi16ByteReplicate() const1688*9880d681SAndroid Build Coastguard Worker bool isNEONi16ByteReplicate() const { return isNEONByteReplicate(2); }
isNEONi32ByteReplicate() const1689*9880d681SAndroid Build Coastguard Worker bool isNEONi32ByteReplicate() const { return isNEONByteReplicate(4); }
isNEONi32vmov() const1690*9880d681SAndroid Build Coastguard Worker bool isNEONi32vmov() const {
1691*9880d681SAndroid Build Coastguard Worker if (isNEONByteReplicate(4))
1692*9880d681SAndroid Build Coastguard Worker return false; // Let it to be classified as byte-replicate case.
1693*9880d681SAndroid Build Coastguard Worker if (!isImm())
1694*9880d681SAndroid Build Coastguard Worker return false;
1695*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1696*9880d681SAndroid Build Coastguard Worker // Must be a constant.
1697*9880d681SAndroid Build Coastguard Worker if (!CE)
1698*9880d681SAndroid Build Coastguard Worker return false;
1699*9880d681SAndroid Build Coastguard Worker int64_t Value = CE->getValue();
1700*9880d681SAndroid Build Coastguard Worker // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1701*9880d681SAndroid Build Coastguard Worker // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1702*9880d681SAndroid Build Coastguard Worker // FIXME: This is probably wrong and a copy and paste from previous example
1703*9880d681SAndroid Build Coastguard Worker return (Value >= 0 && Value < 256) ||
1704*9880d681SAndroid Build Coastguard Worker (Value >= 0x0100 && Value <= 0xff00) ||
1705*9880d681SAndroid Build Coastguard Worker (Value >= 0x010000 && Value <= 0xff0000) ||
1706*9880d681SAndroid Build Coastguard Worker (Value >= 0x01000000 && Value <= 0xff000000) ||
1707*9880d681SAndroid Build Coastguard Worker (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1708*9880d681SAndroid Build Coastguard Worker (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1709*9880d681SAndroid Build Coastguard Worker }
isNEONi32vmovNeg() const1710*9880d681SAndroid Build Coastguard Worker bool isNEONi32vmovNeg() const {
1711*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1712*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1713*9880d681SAndroid Build Coastguard Worker // Must be a constant.
1714*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1715*9880d681SAndroid Build Coastguard Worker int64_t Value = ~CE->getValue();
1716*9880d681SAndroid Build Coastguard Worker // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1717*9880d681SAndroid Build Coastguard Worker // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1718*9880d681SAndroid Build Coastguard Worker // FIXME: This is probably wrong and a copy and paste from previous example
1719*9880d681SAndroid Build Coastguard Worker return (Value >= 0 && Value < 256) ||
1720*9880d681SAndroid Build Coastguard Worker (Value >= 0x0100 && Value <= 0xff00) ||
1721*9880d681SAndroid Build Coastguard Worker (Value >= 0x010000 && Value <= 0xff0000) ||
1722*9880d681SAndroid Build Coastguard Worker (Value >= 0x01000000 && Value <= 0xff000000) ||
1723*9880d681SAndroid Build Coastguard Worker (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1724*9880d681SAndroid Build Coastguard Worker (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1725*9880d681SAndroid Build Coastguard Worker }
1726*9880d681SAndroid Build Coastguard Worker
isNEONi64splat() const1727*9880d681SAndroid Build Coastguard Worker bool isNEONi64splat() const {
1728*9880d681SAndroid Build Coastguard Worker if (!isImm()) return false;
1729*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1730*9880d681SAndroid Build Coastguard Worker // Must be a constant.
1731*9880d681SAndroid Build Coastguard Worker if (!CE) return false;
1732*9880d681SAndroid Build Coastguard Worker uint64_t Value = CE->getValue();
1733*9880d681SAndroid Build Coastguard Worker // i64 value with each byte being either 0 or 0xff.
1734*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 8; ++i, Value >>= 8)
1735*9880d681SAndroid Build Coastguard Worker if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1736*9880d681SAndroid Build Coastguard Worker return true;
1737*9880d681SAndroid Build Coastguard Worker }
1738*9880d681SAndroid Build Coastguard Worker
addExpr(MCInst & Inst,const MCExpr * Expr) const1739*9880d681SAndroid Build Coastguard Worker void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1740*9880d681SAndroid Build Coastguard Worker // Add as immediates when possible. Null MCExpr = 0.
1741*9880d681SAndroid Build Coastguard Worker if (!Expr)
1742*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(0));
1743*9880d681SAndroid Build Coastguard Worker else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1744*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CE->getValue()));
1745*9880d681SAndroid Build Coastguard Worker else
1746*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createExpr(Expr));
1747*9880d681SAndroid Build Coastguard Worker }
1748*9880d681SAndroid Build Coastguard Worker
addARMBranchTargetOperands(MCInst & Inst,unsigned N) const1749*9880d681SAndroid Build Coastguard Worker void addARMBranchTargetOperands(MCInst &Inst, unsigned N) const {
1750*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1751*9880d681SAndroid Build Coastguard Worker addExpr(Inst, getImm());
1752*9880d681SAndroid Build Coastguard Worker }
1753*9880d681SAndroid Build Coastguard Worker
addThumbBranchTargetOperands(MCInst & Inst,unsigned N) const1754*9880d681SAndroid Build Coastguard Worker void addThumbBranchTargetOperands(MCInst &Inst, unsigned N) const {
1755*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1756*9880d681SAndroid Build Coastguard Worker addExpr(Inst, getImm());
1757*9880d681SAndroid Build Coastguard Worker }
1758*9880d681SAndroid Build Coastguard Worker
addCondCodeOperands(MCInst & Inst,unsigned N) const1759*9880d681SAndroid Build Coastguard Worker void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1760*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
1761*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(unsigned(getCondCode())));
1762*9880d681SAndroid Build Coastguard Worker unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1763*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(RegNum));
1764*9880d681SAndroid Build Coastguard Worker }
1765*9880d681SAndroid Build Coastguard Worker
addCoprocNumOperands(MCInst & Inst,unsigned N) const1766*9880d681SAndroid Build Coastguard Worker void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1767*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1768*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(getCoproc()));
1769*9880d681SAndroid Build Coastguard Worker }
1770*9880d681SAndroid Build Coastguard Worker
addCoprocRegOperands(MCInst & Inst,unsigned N) const1771*9880d681SAndroid Build Coastguard Worker void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1772*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1773*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(getCoproc()));
1774*9880d681SAndroid Build Coastguard Worker }
1775*9880d681SAndroid Build Coastguard Worker
addCoprocOptionOperands(MCInst & Inst,unsigned N) const1776*9880d681SAndroid Build Coastguard Worker void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1777*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1778*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CoprocOption.Val));
1779*9880d681SAndroid Build Coastguard Worker }
1780*9880d681SAndroid Build Coastguard Worker
addITMaskOperands(MCInst & Inst,unsigned N) const1781*9880d681SAndroid Build Coastguard Worker void addITMaskOperands(MCInst &Inst, unsigned N) const {
1782*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1783*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(ITMask.Mask));
1784*9880d681SAndroid Build Coastguard Worker }
1785*9880d681SAndroid Build Coastguard Worker
addITCondCodeOperands(MCInst & Inst,unsigned N) const1786*9880d681SAndroid Build Coastguard Worker void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1787*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1788*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(unsigned(getCondCode())));
1789*9880d681SAndroid Build Coastguard Worker }
1790*9880d681SAndroid Build Coastguard Worker
addCCOutOperands(MCInst & Inst,unsigned N) const1791*9880d681SAndroid Build Coastguard Worker void addCCOutOperands(MCInst &Inst, unsigned N) const {
1792*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1793*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(getReg()));
1794*9880d681SAndroid Build Coastguard Worker }
1795*9880d681SAndroid Build Coastguard Worker
addRegOperands(MCInst & Inst,unsigned N) const1796*9880d681SAndroid Build Coastguard Worker void addRegOperands(MCInst &Inst, unsigned N) const {
1797*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1798*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(getReg()));
1799*9880d681SAndroid Build Coastguard Worker }
1800*9880d681SAndroid Build Coastguard Worker
addRegShiftedRegOperands(MCInst & Inst,unsigned N) const1801*9880d681SAndroid Build Coastguard Worker void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
1802*9880d681SAndroid Build Coastguard Worker assert(N == 3 && "Invalid number of operands!");
1803*9880d681SAndroid Build Coastguard Worker assert(isRegShiftedReg() &&
1804*9880d681SAndroid Build Coastguard Worker "addRegShiftedRegOperands() on non-RegShiftedReg!");
1805*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(RegShiftedReg.SrcReg));
1806*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(RegShiftedReg.ShiftReg));
1807*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(
1808*9880d681SAndroid Build Coastguard Worker ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
1809*9880d681SAndroid Build Coastguard Worker }
1810*9880d681SAndroid Build Coastguard Worker
addRegShiftedImmOperands(MCInst & Inst,unsigned N) const1811*9880d681SAndroid Build Coastguard Worker void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
1812*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
1813*9880d681SAndroid Build Coastguard Worker assert(isRegShiftedImm() &&
1814*9880d681SAndroid Build Coastguard Worker "addRegShiftedImmOperands() on non-RegShiftedImm!");
1815*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(RegShiftedImm.SrcReg));
1816*9880d681SAndroid Build Coastguard Worker // Shift of #32 is encoded as 0 where permitted
1817*9880d681SAndroid Build Coastguard Worker unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm);
1818*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(
1819*9880d681SAndroid Build Coastguard Worker ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm)));
1820*9880d681SAndroid Build Coastguard Worker }
1821*9880d681SAndroid Build Coastguard Worker
addShifterImmOperands(MCInst & Inst,unsigned N) const1822*9880d681SAndroid Build Coastguard Worker void addShifterImmOperands(MCInst &Inst, unsigned N) const {
1823*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1824*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm((ShifterImm.isASR << 5) |
1825*9880d681SAndroid Build Coastguard Worker ShifterImm.Imm));
1826*9880d681SAndroid Build Coastguard Worker }
1827*9880d681SAndroid Build Coastguard Worker
addRegListOperands(MCInst & Inst,unsigned N) const1828*9880d681SAndroid Build Coastguard Worker void addRegListOperands(MCInst &Inst, unsigned N) const {
1829*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1830*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<unsigned> &RegList = getRegList();
1831*9880d681SAndroid Build Coastguard Worker for (SmallVectorImpl<unsigned>::const_iterator
1832*9880d681SAndroid Build Coastguard Worker I = RegList.begin(), E = RegList.end(); I != E; ++I)
1833*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(*I));
1834*9880d681SAndroid Build Coastguard Worker }
1835*9880d681SAndroid Build Coastguard Worker
addDPRRegListOperands(MCInst & Inst,unsigned N) const1836*9880d681SAndroid Build Coastguard Worker void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1837*9880d681SAndroid Build Coastguard Worker addRegListOperands(Inst, N);
1838*9880d681SAndroid Build Coastguard Worker }
1839*9880d681SAndroid Build Coastguard Worker
addSPRRegListOperands(MCInst & Inst,unsigned N) const1840*9880d681SAndroid Build Coastguard Worker void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1841*9880d681SAndroid Build Coastguard Worker addRegListOperands(Inst, N);
1842*9880d681SAndroid Build Coastguard Worker }
1843*9880d681SAndroid Build Coastguard Worker
addRotImmOperands(MCInst & Inst,unsigned N) const1844*9880d681SAndroid Build Coastguard Worker void addRotImmOperands(MCInst &Inst, unsigned N) const {
1845*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1846*9880d681SAndroid Build Coastguard Worker // Encoded as val>>3. The printer handles display as 8, 16, 24.
1847*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(RotImm.Imm >> 3));
1848*9880d681SAndroid Build Coastguard Worker }
1849*9880d681SAndroid Build Coastguard Worker
addModImmOperands(MCInst & Inst,unsigned N) const1850*9880d681SAndroid Build Coastguard Worker void addModImmOperands(MCInst &Inst, unsigned N) const {
1851*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1852*9880d681SAndroid Build Coastguard Worker
1853*9880d681SAndroid Build Coastguard Worker // Support for fixups (MCFixup)
1854*9880d681SAndroid Build Coastguard Worker if (isImm())
1855*9880d681SAndroid Build Coastguard Worker return addImmOperands(Inst, N);
1856*9880d681SAndroid Build Coastguard Worker
1857*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(ModImm.Bits | (ModImm.Rot << 7)));
1858*9880d681SAndroid Build Coastguard Worker }
1859*9880d681SAndroid Build Coastguard Worker
addModImmNotOperands(MCInst & Inst,unsigned N) const1860*9880d681SAndroid Build Coastguard Worker void addModImmNotOperands(MCInst &Inst, unsigned N) const {
1861*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1862*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1863*9880d681SAndroid Build Coastguard Worker uint32_t Enc = ARM_AM::getSOImmVal(~CE->getValue());
1864*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Enc));
1865*9880d681SAndroid Build Coastguard Worker }
1866*9880d681SAndroid Build Coastguard Worker
addModImmNegOperands(MCInst & Inst,unsigned N) const1867*9880d681SAndroid Build Coastguard Worker void addModImmNegOperands(MCInst &Inst, unsigned N) const {
1868*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1869*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1870*9880d681SAndroid Build Coastguard Worker uint32_t Enc = ARM_AM::getSOImmVal(-CE->getValue());
1871*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Enc));
1872*9880d681SAndroid Build Coastguard Worker }
1873*9880d681SAndroid Build Coastguard Worker
addBitfieldOperands(MCInst & Inst,unsigned N) const1874*9880d681SAndroid Build Coastguard Worker void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1875*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1876*9880d681SAndroid Build Coastguard Worker // Munge the lsb/width into a bitfield mask.
1877*9880d681SAndroid Build Coastguard Worker unsigned lsb = Bitfield.LSB;
1878*9880d681SAndroid Build Coastguard Worker unsigned width = Bitfield.Width;
1879*9880d681SAndroid Build Coastguard Worker // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1880*9880d681SAndroid Build Coastguard Worker uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1881*9880d681SAndroid Build Coastguard Worker (32 - (lsb + width)));
1882*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Mask));
1883*9880d681SAndroid Build Coastguard Worker }
1884*9880d681SAndroid Build Coastguard Worker
addImmOperands(MCInst & Inst,unsigned N) const1885*9880d681SAndroid Build Coastguard Worker void addImmOperands(MCInst &Inst, unsigned N) const {
1886*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1887*9880d681SAndroid Build Coastguard Worker addExpr(Inst, getImm());
1888*9880d681SAndroid Build Coastguard Worker }
1889*9880d681SAndroid Build Coastguard Worker
addFBits16Operands(MCInst & Inst,unsigned N) const1890*9880d681SAndroid Build Coastguard Worker void addFBits16Operands(MCInst &Inst, unsigned N) const {
1891*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1892*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1893*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(16 - CE->getValue()));
1894*9880d681SAndroid Build Coastguard Worker }
1895*9880d681SAndroid Build Coastguard Worker
addFBits32Operands(MCInst & Inst,unsigned N) const1896*9880d681SAndroid Build Coastguard Worker void addFBits32Operands(MCInst &Inst, unsigned N) const {
1897*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1898*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1899*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(32 - CE->getValue()));
1900*9880d681SAndroid Build Coastguard Worker }
1901*9880d681SAndroid Build Coastguard Worker
addFPImmOperands(MCInst & Inst,unsigned N) const1902*9880d681SAndroid Build Coastguard Worker void addFPImmOperands(MCInst &Inst, unsigned N) const {
1903*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1904*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1905*9880d681SAndroid Build Coastguard Worker int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1906*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
1907*9880d681SAndroid Build Coastguard Worker }
1908*9880d681SAndroid Build Coastguard Worker
addImm8s4Operands(MCInst & Inst,unsigned N) const1909*9880d681SAndroid Build Coastguard Worker void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1910*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1911*9880d681SAndroid Build Coastguard Worker // FIXME: We really want to scale the value here, but the LDRD/STRD
1912*9880d681SAndroid Build Coastguard Worker // instruction don't encode operands that way yet.
1913*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1914*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CE->getValue()));
1915*9880d681SAndroid Build Coastguard Worker }
1916*9880d681SAndroid Build Coastguard Worker
addImm0_1020s4Operands(MCInst & Inst,unsigned N) const1917*9880d681SAndroid Build Coastguard Worker void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1918*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1919*9880d681SAndroid Build Coastguard Worker // The immediate is scaled by four in the encoding and is stored
1920*9880d681SAndroid Build Coastguard Worker // in the MCInst as such. Lop off the low two bits here.
1921*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1922*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CE->getValue() / 4));
1923*9880d681SAndroid Build Coastguard Worker }
1924*9880d681SAndroid Build Coastguard Worker
addImm0_508s4NegOperands(MCInst & Inst,unsigned N) const1925*9880d681SAndroid Build Coastguard Worker void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
1926*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1927*9880d681SAndroid Build Coastguard Worker // The immediate is scaled by four in the encoding and is stored
1928*9880d681SAndroid Build Coastguard Worker // in the MCInst as such. Lop off the low two bits here.
1929*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1930*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(-(CE->getValue() / 4)));
1931*9880d681SAndroid Build Coastguard Worker }
1932*9880d681SAndroid Build Coastguard Worker
addImm0_508s4Operands(MCInst & Inst,unsigned N) const1933*9880d681SAndroid Build Coastguard Worker void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1934*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1935*9880d681SAndroid Build Coastguard Worker // The immediate is scaled by four in the encoding and is stored
1936*9880d681SAndroid Build Coastguard Worker // in the MCInst as such. Lop off the low two bits here.
1937*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1938*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CE->getValue() / 4));
1939*9880d681SAndroid Build Coastguard Worker }
1940*9880d681SAndroid Build Coastguard Worker
addImm1_16Operands(MCInst & Inst,unsigned N) const1941*9880d681SAndroid Build Coastguard Worker void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1942*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1943*9880d681SAndroid Build Coastguard Worker // The constant encodes as the immediate-1, and we store in the instruction
1944*9880d681SAndroid Build Coastguard Worker // the bits as encoded, so subtract off one here.
1945*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1946*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CE->getValue() - 1));
1947*9880d681SAndroid Build Coastguard Worker }
1948*9880d681SAndroid Build Coastguard Worker
addImm1_32Operands(MCInst & Inst,unsigned N) const1949*9880d681SAndroid Build Coastguard Worker void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1950*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1951*9880d681SAndroid Build Coastguard Worker // The constant encodes as the immediate-1, and we store in the instruction
1952*9880d681SAndroid Build Coastguard Worker // the bits as encoded, so subtract off one here.
1953*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1954*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CE->getValue() - 1));
1955*9880d681SAndroid Build Coastguard Worker }
1956*9880d681SAndroid Build Coastguard Worker
addImmThumbSROperands(MCInst & Inst,unsigned N) const1957*9880d681SAndroid Build Coastguard Worker void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1958*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1959*9880d681SAndroid Build Coastguard Worker // The constant encodes as the immediate, except for 32, which encodes as
1960*9880d681SAndroid Build Coastguard Worker // zero.
1961*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1962*9880d681SAndroid Build Coastguard Worker unsigned Imm = CE->getValue();
1963*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm((Imm == 32 ? 0 : Imm)));
1964*9880d681SAndroid Build Coastguard Worker }
1965*9880d681SAndroid Build Coastguard Worker
addPKHASRImmOperands(MCInst & Inst,unsigned N) const1966*9880d681SAndroid Build Coastguard Worker void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1967*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1968*9880d681SAndroid Build Coastguard Worker // An ASR value of 32 encodes as 0, so that's how we want to add it to
1969*9880d681SAndroid Build Coastguard Worker // the instruction as well.
1970*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1971*9880d681SAndroid Build Coastguard Worker int Val = CE->getValue();
1972*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val == 32 ? 0 : Val));
1973*9880d681SAndroid Build Coastguard Worker }
1974*9880d681SAndroid Build Coastguard Worker
addT2SOImmNotOperands(MCInst & Inst,unsigned N) const1975*9880d681SAndroid Build Coastguard Worker void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1976*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1977*9880d681SAndroid Build Coastguard Worker // The operand is actually a t2_so_imm, but we have its bitwise
1978*9880d681SAndroid Build Coastguard Worker // negation in the assembly source, so twiddle it here.
1979*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1980*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(~CE->getValue()));
1981*9880d681SAndroid Build Coastguard Worker }
1982*9880d681SAndroid Build Coastguard Worker
addT2SOImmNegOperands(MCInst & Inst,unsigned N) const1983*9880d681SAndroid Build Coastguard Worker void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1984*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1985*9880d681SAndroid Build Coastguard Worker // The operand is actually a t2_so_imm, but we have its
1986*9880d681SAndroid Build Coastguard Worker // negation in the assembly source, so twiddle it here.
1987*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1988*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(-CE->getValue()));
1989*9880d681SAndroid Build Coastguard Worker }
1990*9880d681SAndroid Build Coastguard Worker
addImm0_4095NegOperands(MCInst & Inst,unsigned N) const1991*9880d681SAndroid Build Coastguard Worker void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
1992*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
1993*9880d681SAndroid Build Coastguard Worker // The operand is actually an imm0_4095, but we have its
1994*9880d681SAndroid Build Coastguard Worker // negation in the assembly source, so twiddle it here.
1995*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1996*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(-CE->getValue()));
1997*9880d681SAndroid Build Coastguard Worker }
1998*9880d681SAndroid Build Coastguard Worker
addUnsignedOffset_b8s2Operands(MCInst & Inst,unsigned N) const1999*9880d681SAndroid Build Coastguard Worker void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const {
2000*9880d681SAndroid Build Coastguard Worker if(const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) {
2001*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CE->getValue() >> 2));
2002*9880d681SAndroid Build Coastguard Worker return;
2003*9880d681SAndroid Build Coastguard Worker }
2004*9880d681SAndroid Build Coastguard Worker
2005*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
2006*9880d681SAndroid Build Coastguard Worker assert(SR && "Unknown value type!");
2007*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createExpr(SR));
2008*9880d681SAndroid Build Coastguard Worker }
2009*9880d681SAndroid Build Coastguard Worker
addThumbMemPCOperands(MCInst & Inst,unsigned N) const2010*9880d681SAndroid Build Coastguard Worker void addThumbMemPCOperands(MCInst &Inst, unsigned N) const {
2011*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2012*9880d681SAndroid Build Coastguard Worker if (isImm()) {
2013*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2014*9880d681SAndroid Build Coastguard Worker if (CE) {
2015*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CE->getValue()));
2016*9880d681SAndroid Build Coastguard Worker return;
2017*9880d681SAndroid Build Coastguard Worker }
2018*9880d681SAndroid Build Coastguard Worker
2019*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
2020*9880d681SAndroid Build Coastguard Worker
2021*9880d681SAndroid Build Coastguard Worker assert(SR && "Unknown value type!");
2022*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createExpr(SR));
2023*9880d681SAndroid Build Coastguard Worker return;
2024*9880d681SAndroid Build Coastguard Worker }
2025*9880d681SAndroid Build Coastguard Worker
2026*9880d681SAndroid Build Coastguard Worker assert(isMem() && "Unknown value type!");
2027*9880d681SAndroid Build Coastguard Worker assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!");
2028*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Memory.OffsetImm->getValue()));
2029*9880d681SAndroid Build Coastguard Worker }
2030*9880d681SAndroid Build Coastguard Worker
addMemBarrierOptOperands(MCInst & Inst,unsigned N) const2031*9880d681SAndroid Build Coastguard Worker void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
2032*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2033*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(unsigned(getMemBarrierOpt())));
2034*9880d681SAndroid Build Coastguard Worker }
2035*9880d681SAndroid Build Coastguard Worker
addInstSyncBarrierOptOperands(MCInst & Inst,unsigned N) const2036*9880d681SAndroid Build Coastguard Worker void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const {
2037*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2038*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(unsigned(getInstSyncBarrierOpt())));
2039*9880d681SAndroid Build Coastguard Worker }
2040*9880d681SAndroid Build Coastguard Worker
addMemNoOffsetOperands(MCInst & Inst,unsigned N) const2041*9880d681SAndroid Build Coastguard Worker void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
2042*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2043*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2044*9880d681SAndroid Build Coastguard Worker }
2045*9880d681SAndroid Build Coastguard Worker
addMemPCRelImm12Operands(MCInst & Inst,unsigned N) const2046*9880d681SAndroid Build Coastguard Worker void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
2047*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2048*9880d681SAndroid Build Coastguard Worker int32_t Imm = Memory.OffsetImm->getValue();
2049*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Imm));
2050*9880d681SAndroid Build Coastguard Worker }
2051*9880d681SAndroid Build Coastguard Worker
addAdrLabelOperands(MCInst & Inst,unsigned N) const2052*9880d681SAndroid Build Coastguard Worker void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
2053*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2054*9880d681SAndroid Build Coastguard Worker assert(isImm() && "Not an immediate!");
2055*9880d681SAndroid Build Coastguard Worker
2056*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
2057*9880d681SAndroid Build Coastguard Worker // reference needing a fixup.
2058*9880d681SAndroid Build Coastguard Worker if (!isa<MCConstantExpr>(getImm())) {
2059*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createExpr(getImm()));
2060*9880d681SAndroid Build Coastguard Worker return;
2061*9880d681SAndroid Build Coastguard Worker }
2062*9880d681SAndroid Build Coastguard Worker
2063*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2064*9880d681SAndroid Build Coastguard Worker int Val = CE->getValue();
2065*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2066*9880d681SAndroid Build Coastguard Worker }
2067*9880d681SAndroid Build Coastguard Worker
addAlignedMemoryOperands(MCInst & Inst,unsigned N) const2068*9880d681SAndroid Build Coastguard Worker void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
2069*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2070*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2071*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Memory.Alignment));
2072*9880d681SAndroid Build Coastguard Worker }
2073*9880d681SAndroid Build Coastguard Worker
addDupAlignedMemoryNoneOperands(MCInst & Inst,unsigned N) const2074*9880d681SAndroid Build Coastguard Worker void addDupAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const {
2075*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2076*9880d681SAndroid Build Coastguard Worker }
2077*9880d681SAndroid Build Coastguard Worker
addAlignedMemoryNoneOperands(MCInst & Inst,unsigned N) const2078*9880d681SAndroid Build Coastguard Worker void addAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const {
2079*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2080*9880d681SAndroid Build Coastguard Worker }
2081*9880d681SAndroid Build Coastguard Worker
addAlignedMemory16Operands(MCInst & Inst,unsigned N) const2082*9880d681SAndroid Build Coastguard Worker void addAlignedMemory16Operands(MCInst &Inst, unsigned N) const {
2083*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2084*9880d681SAndroid Build Coastguard Worker }
2085*9880d681SAndroid Build Coastguard Worker
addDupAlignedMemory16Operands(MCInst & Inst,unsigned N) const2086*9880d681SAndroid Build Coastguard Worker void addDupAlignedMemory16Operands(MCInst &Inst, unsigned N) const {
2087*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2088*9880d681SAndroid Build Coastguard Worker }
2089*9880d681SAndroid Build Coastguard Worker
addAlignedMemory32Operands(MCInst & Inst,unsigned N) const2090*9880d681SAndroid Build Coastguard Worker void addAlignedMemory32Operands(MCInst &Inst, unsigned N) const {
2091*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2092*9880d681SAndroid Build Coastguard Worker }
2093*9880d681SAndroid Build Coastguard Worker
addDupAlignedMemory32Operands(MCInst & Inst,unsigned N) const2094*9880d681SAndroid Build Coastguard Worker void addDupAlignedMemory32Operands(MCInst &Inst, unsigned N) const {
2095*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2096*9880d681SAndroid Build Coastguard Worker }
2097*9880d681SAndroid Build Coastguard Worker
addAlignedMemory64Operands(MCInst & Inst,unsigned N) const2098*9880d681SAndroid Build Coastguard Worker void addAlignedMemory64Operands(MCInst &Inst, unsigned N) const {
2099*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2100*9880d681SAndroid Build Coastguard Worker }
2101*9880d681SAndroid Build Coastguard Worker
addDupAlignedMemory64Operands(MCInst & Inst,unsigned N) const2102*9880d681SAndroid Build Coastguard Worker void addDupAlignedMemory64Operands(MCInst &Inst, unsigned N) const {
2103*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2104*9880d681SAndroid Build Coastguard Worker }
2105*9880d681SAndroid Build Coastguard Worker
addAlignedMemory64or128Operands(MCInst & Inst,unsigned N) const2106*9880d681SAndroid Build Coastguard Worker void addAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const {
2107*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2108*9880d681SAndroid Build Coastguard Worker }
2109*9880d681SAndroid Build Coastguard Worker
addDupAlignedMemory64or128Operands(MCInst & Inst,unsigned N) const2110*9880d681SAndroid Build Coastguard Worker void addDupAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const {
2111*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2112*9880d681SAndroid Build Coastguard Worker }
2113*9880d681SAndroid Build Coastguard Worker
addAlignedMemory64or128or256Operands(MCInst & Inst,unsigned N) const2114*9880d681SAndroid Build Coastguard Worker void addAlignedMemory64or128or256Operands(MCInst &Inst, unsigned N) const {
2115*9880d681SAndroid Build Coastguard Worker addAlignedMemoryOperands(Inst, N);
2116*9880d681SAndroid Build Coastguard Worker }
2117*9880d681SAndroid Build Coastguard Worker
addAddrMode2Operands(MCInst & Inst,unsigned N) const2118*9880d681SAndroid Build Coastguard Worker void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
2119*9880d681SAndroid Build Coastguard Worker assert(N == 3 && "Invalid number of operands!");
2120*9880d681SAndroid Build Coastguard Worker int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2121*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetRegNum) {
2122*9880d681SAndroid Build Coastguard Worker ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2123*9880d681SAndroid Build Coastguard Worker // Special case for #-0
2124*9880d681SAndroid Build Coastguard Worker if (Val == INT32_MIN) Val = 0;
2125*9880d681SAndroid Build Coastguard Worker if (Val < 0) Val = -Val;
2126*9880d681SAndroid Build Coastguard Worker Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
2127*9880d681SAndroid Build Coastguard Worker } else {
2128*9880d681SAndroid Build Coastguard Worker // For register offset, we encode the shift type and negation flag
2129*9880d681SAndroid Build Coastguard Worker // here.
2130*9880d681SAndroid Build Coastguard Worker Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
2131*9880d681SAndroid Build Coastguard Worker Memory.ShiftImm, Memory.ShiftType);
2132*9880d681SAndroid Build Coastguard Worker }
2133*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2134*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2135*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2136*9880d681SAndroid Build Coastguard Worker }
2137*9880d681SAndroid Build Coastguard Worker
addAM2OffsetImmOperands(MCInst & Inst,unsigned N) const2138*9880d681SAndroid Build Coastguard Worker void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
2139*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2140*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2141*9880d681SAndroid Build Coastguard Worker assert(CE && "non-constant AM2OffsetImm operand!");
2142*9880d681SAndroid Build Coastguard Worker int32_t Val = CE->getValue();
2143*9880d681SAndroid Build Coastguard Worker ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2144*9880d681SAndroid Build Coastguard Worker // Special case for #-0
2145*9880d681SAndroid Build Coastguard Worker if (Val == INT32_MIN) Val = 0;
2146*9880d681SAndroid Build Coastguard Worker if (Val < 0) Val = -Val;
2147*9880d681SAndroid Build Coastguard Worker Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
2148*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(0));
2149*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2150*9880d681SAndroid Build Coastguard Worker }
2151*9880d681SAndroid Build Coastguard Worker
addAddrMode3Operands(MCInst & Inst,unsigned N) const2152*9880d681SAndroid Build Coastguard Worker void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
2153*9880d681SAndroid Build Coastguard Worker assert(N == 3 && "Invalid number of operands!");
2154*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
2155*9880d681SAndroid Build Coastguard Worker // reference needing a fixup. If it is a constant, it's something else
2156*9880d681SAndroid Build Coastguard Worker // and we reject it.
2157*9880d681SAndroid Build Coastguard Worker if (isImm()) {
2158*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createExpr(getImm()));
2159*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(0));
2160*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(0));
2161*9880d681SAndroid Build Coastguard Worker return;
2162*9880d681SAndroid Build Coastguard Worker }
2163*9880d681SAndroid Build Coastguard Worker
2164*9880d681SAndroid Build Coastguard Worker int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2165*9880d681SAndroid Build Coastguard Worker if (!Memory.OffsetRegNum) {
2166*9880d681SAndroid Build Coastguard Worker ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2167*9880d681SAndroid Build Coastguard Worker // Special case for #-0
2168*9880d681SAndroid Build Coastguard Worker if (Val == INT32_MIN) Val = 0;
2169*9880d681SAndroid Build Coastguard Worker if (Val < 0) Val = -Val;
2170*9880d681SAndroid Build Coastguard Worker Val = ARM_AM::getAM3Opc(AddSub, Val);
2171*9880d681SAndroid Build Coastguard Worker } else {
2172*9880d681SAndroid Build Coastguard Worker // For register offset, we encode the shift type and negation flag
2173*9880d681SAndroid Build Coastguard Worker // here.
2174*9880d681SAndroid Build Coastguard Worker Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
2175*9880d681SAndroid Build Coastguard Worker }
2176*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2177*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2178*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2179*9880d681SAndroid Build Coastguard Worker }
2180*9880d681SAndroid Build Coastguard Worker
addAM3OffsetOperands(MCInst & Inst,unsigned N) const2181*9880d681SAndroid Build Coastguard Worker void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
2182*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2183*9880d681SAndroid Build Coastguard Worker if (Kind == k_PostIndexRegister) {
2184*9880d681SAndroid Build Coastguard Worker int32_t Val =
2185*9880d681SAndroid Build Coastguard Worker ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
2186*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum));
2187*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2188*9880d681SAndroid Build Coastguard Worker return;
2189*9880d681SAndroid Build Coastguard Worker }
2190*9880d681SAndroid Build Coastguard Worker
2191*9880d681SAndroid Build Coastguard Worker // Constant offset.
2192*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
2193*9880d681SAndroid Build Coastguard Worker int32_t Val = CE->getValue();
2194*9880d681SAndroid Build Coastguard Worker ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2195*9880d681SAndroid Build Coastguard Worker // Special case for #-0
2196*9880d681SAndroid Build Coastguard Worker if (Val == INT32_MIN) Val = 0;
2197*9880d681SAndroid Build Coastguard Worker if (Val < 0) Val = -Val;
2198*9880d681SAndroid Build Coastguard Worker Val = ARM_AM::getAM3Opc(AddSub, Val);
2199*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(0));
2200*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2201*9880d681SAndroid Build Coastguard Worker }
2202*9880d681SAndroid Build Coastguard Worker
addAddrMode5Operands(MCInst & Inst,unsigned N) const2203*9880d681SAndroid Build Coastguard Worker void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
2204*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2205*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
2206*9880d681SAndroid Build Coastguard Worker // reference needing a fixup. If it is a constant, it's something else
2207*9880d681SAndroid Build Coastguard Worker // and we reject it.
2208*9880d681SAndroid Build Coastguard Worker if (isImm()) {
2209*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createExpr(getImm()));
2210*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(0));
2211*9880d681SAndroid Build Coastguard Worker return;
2212*9880d681SAndroid Build Coastguard Worker }
2213*9880d681SAndroid Build Coastguard Worker
2214*9880d681SAndroid Build Coastguard Worker // The lower two bits are always zero and as such are not encoded.
2215*9880d681SAndroid Build Coastguard Worker int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
2216*9880d681SAndroid Build Coastguard Worker ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2217*9880d681SAndroid Build Coastguard Worker // Special case for #-0
2218*9880d681SAndroid Build Coastguard Worker if (Val == INT32_MIN) Val = 0;
2219*9880d681SAndroid Build Coastguard Worker if (Val < 0) Val = -Val;
2220*9880d681SAndroid Build Coastguard Worker Val = ARM_AM::getAM5Opc(AddSub, Val);
2221*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2222*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2223*9880d681SAndroid Build Coastguard Worker }
2224*9880d681SAndroid Build Coastguard Worker
addAddrMode5FP16Operands(MCInst & Inst,unsigned N) const2225*9880d681SAndroid Build Coastguard Worker void addAddrMode5FP16Operands(MCInst &Inst, unsigned N) const {
2226*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2227*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
2228*9880d681SAndroid Build Coastguard Worker // reference needing a fixup. If it is a constant, it's something else
2229*9880d681SAndroid Build Coastguard Worker // and we reject it.
2230*9880d681SAndroid Build Coastguard Worker if (isImm()) {
2231*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createExpr(getImm()));
2232*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(0));
2233*9880d681SAndroid Build Coastguard Worker return;
2234*9880d681SAndroid Build Coastguard Worker }
2235*9880d681SAndroid Build Coastguard Worker
2236*9880d681SAndroid Build Coastguard Worker // The lower bit is always zero and as such is not encoded.
2237*9880d681SAndroid Build Coastguard Worker int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 2 : 0;
2238*9880d681SAndroid Build Coastguard Worker ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2239*9880d681SAndroid Build Coastguard Worker // Special case for #-0
2240*9880d681SAndroid Build Coastguard Worker if (Val == INT32_MIN) Val = 0;
2241*9880d681SAndroid Build Coastguard Worker if (Val < 0) Val = -Val;
2242*9880d681SAndroid Build Coastguard Worker Val = ARM_AM::getAM5FP16Opc(AddSub, Val);
2243*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2244*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2245*9880d681SAndroid Build Coastguard Worker }
2246*9880d681SAndroid Build Coastguard Worker
addMemImm8s4OffsetOperands(MCInst & Inst,unsigned N) const2247*9880d681SAndroid Build Coastguard Worker void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
2248*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2249*9880d681SAndroid Build Coastguard Worker // If we have an immediate that's not a constant, treat it as a label
2250*9880d681SAndroid Build Coastguard Worker // reference needing a fixup. If it is a constant, it's something else
2251*9880d681SAndroid Build Coastguard Worker // and we reject it.
2252*9880d681SAndroid Build Coastguard Worker if (isImm()) {
2253*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createExpr(getImm()));
2254*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(0));
2255*9880d681SAndroid Build Coastguard Worker return;
2256*9880d681SAndroid Build Coastguard Worker }
2257*9880d681SAndroid Build Coastguard Worker
2258*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2259*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2260*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2261*9880d681SAndroid Build Coastguard Worker }
2262*9880d681SAndroid Build Coastguard Worker
addMemImm0_1020s4OffsetOperands(MCInst & Inst,unsigned N) const2263*9880d681SAndroid Build Coastguard Worker void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
2264*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2265*9880d681SAndroid Build Coastguard Worker // The lower two bits are always zero and as such are not encoded.
2266*9880d681SAndroid Build Coastguard Worker int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
2267*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2268*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2269*9880d681SAndroid Build Coastguard Worker }
2270*9880d681SAndroid Build Coastguard Worker
addMemImm8OffsetOperands(MCInst & Inst,unsigned N) const2271*9880d681SAndroid Build Coastguard Worker void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
2272*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2273*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2274*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2275*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2276*9880d681SAndroid Build Coastguard Worker }
2277*9880d681SAndroid Build Coastguard Worker
addMemPosImm8OffsetOperands(MCInst & Inst,unsigned N) const2278*9880d681SAndroid Build Coastguard Worker void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
2279*9880d681SAndroid Build Coastguard Worker addMemImm8OffsetOperands(Inst, N);
2280*9880d681SAndroid Build Coastguard Worker }
2281*9880d681SAndroid Build Coastguard Worker
addMemNegImm8OffsetOperands(MCInst & Inst,unsigned N) const2282*9880d681SAndroid Build Coastguard Worker void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
2283*9880d681SAndroid Build Coastguard Worker addMemImm8OffsetOperands(Inst, N);
2284*9880d681SAndroid Build Coastguard Worker }
2285*9880d681SAndroid Build Coastguard Worker
addMemUImm12OffsetOperands(MCInst & Inst,unsigned N) const2286*9880d681SAndroid Build Coastguard Worker void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
2287*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2288*9880d681SAndroid Build Coastguard Worker // If this is an immediate, it's a label reference.
2289*9880d681SAndroid Build Coastguard Worker if (isImm()) {
2290*9880d681SAndroid Build Coastguard Worker addExpr(Inst, getImm());
2291*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(0));
2292*9880d681SAndroid Build Coastguard Worker return;
2293*9880d681SAndroid Build Coastguard Worker }
2294*9880d681SAndroid Build Coastguard Worker
2295*9880d681SAndroid Build Coastguard Worker // Otherwise, it's a normal memory reg+offset.
2296*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2297*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2298*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2299*9880d681SAndroid Build Coastguard Worker }
2300*9880d681SAndroid Build Coastguard Worker
addMemImm12OffsetOperands(MCInst & Inst,unsigned N) const2301*9880d681SAndroid Build Coastguard Worker void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
2302*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2303*9880d681SAndroid Build Coastguard Worker // If this is an immediate, it's a label reference.
2304*9880d681SAndroid Build Coastguard Worker if (isImm()) {
2305*9880d681SAndroid Build Coastguard Worker addExpr(Inst, getImm());
2306*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(0));
2307*9880d681SAndroid Build Coastguard Worker return;
2308*9880d681SAndroid Build Coastguard Worker }
2309*9880d681SAndroid Build Coastguard Worker
2310*9880d681SAndroid Build Coastguard Worker // Otherwise, it's a normal memory reg+offset.
2311*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2312*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2313*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2314*9880d681SAndroid Build Coastguard Worker }
2315*9880d681SAndroid Build Coastguard Worker
addConstPoolAsmImmOperands(MCInst & Inst,unsigned N) const2316*9880d681SAndroid Build Coastguard Worker void addConstPoolAsmImmOperands(MCInst &Inst, unsigned N) const {
2317*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2318*9880d681SAndroid Build Coastguard Worker // This is container for the immediate that we will create the constant
2319*9880d681SAndroid Build Coastguard Worker // pool from
2320*9880d681SAndroid Build Coastguard Worker addExpr(Inst, getConstantPoolImm());
2321*9880d681SAndroid Build Coastguard Worker return;
2322*9880d681SAndroid Build Coastguard Worker }
2323*9880d681SAndroid Build Coastguard Worker
addMemTBBOperands(MCInst & Inst,unsigned N) const2324*9880d681SAndroid Build Coastguard Worker void addMemTBBOperands(MCInst &Inst, unsigned N) const {
2325*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2326*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2327*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2328*9880d681SAndroid Build Coastguard Worker }
2329*9880d681SAndroid Build Coastguard Worker
addMemTBHOperands(MCInst & Inst,unsigned N) const2330*9880d681SAndroid Build Coastguard Worker void addMemTBHOperands(MCInst &Inst, unsigned N) const {
2331*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2332*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2333*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2334*9880d681SAndroid Build Coastguard Worker }
2335*9880d681SAndroid Build Coastguard Worker
addMemRegOffsetOperands(MCInst & Inst,unsigned N) const2336*9880d681SAndroid Build Coastguard Worker void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
2337*9880d681SAndroid Build Coastguard Worker assert(N == 3 && "Invalid number of operands!");
2338*9880d681SAndroid Build Coastguard Worker unsigned Val =
2339*9880d681SAndroid Build Coastguard Worker ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
2340*9880d681SAndroid Build Coastguard Worker Memory.ShiftImm, Memory.ShiftType);
2341*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2342*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2343*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2344*9880d681SAndroid Build Coastguard Worker }
2345*9880d681SAndroid Build Coastguard Worker
addT2MemRegOffsetOperands(MCInst & Inst,unsigned N) const2346*9880d681SAndroid Build Coastguard Worker void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
2347*9880d681SAndroid Build Coastguard Worker assert(N == 3 && "Invalid number of operands!");
2348*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2349*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2350*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Memory.ShiftImm));
2351*9880d681SAndroid Build Coastguard Worker }
2352*9880d681SAndroid Build Coastguard Worker
addMemThumbRROperands(MCInst & Inst,unsigned N) const2353*9880d681SAndroid Build Coastguard Worker void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
2354*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2355*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2356*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2357*9880d681SAndroid Build Coastguard Worker }
2358*9880d681SAndroid Build Coastguard Worker
addMemThumbRIs4Operands(MCInst & Inst,unsigned N) const2359*9880d681SAndroid Build Coastguard Worker void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
2360*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2361*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
2362*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2363*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2364*9880d681SAndroid Build Coastguard Worker }
2365*9880d681SAndroid Build Coastguard Worker
addMemThumbRIs2Operands(MCInst & Inst,unsigned N) const2366*9880d681SAndroid Build Coastguard Worker void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
2367*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2368*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
2369*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2370*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2371*9880d681SAndroid Build Coastguard Worker }
2372*9880d681SAndroid Build Coastguard Worker
addMemThumbRIs1Operands(MCInst & Inst,unsigned N) const2373*9880d681SAndroid Build Coastguard Worker void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
2374*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2375*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
2376*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2377*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2378*9880d681SAndroid Build Coastguard Worker }
2379*9880d681SAndroid Build Coastguard Worker
addMemThumbSPIOperands(MCInst & Inst,unsigned N) const2380*9880d681SAndroid Build Coastguard Worker void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
2381*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2382*9880d681SAndroid Build Coastguard Worker int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
2383*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2384*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Val));
2385*9880d681SAndroid Build Coastguard Worker }
2386*9880d681SAndroid Build Coastguard Worker
addPostIdxImm8Operands(MCInst & Inst,unsigned N) const2387*9880d681SAndroid Build Coastguard Worker void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
2388*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2389*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2390*9880d681SAndroid Build Coastguard Worker assert(CE && "non-constant post-idx-imm8 operand!");
2391*9880d681SAndroid Build Coastguard Worker int Imm = CE->getValue();
2392*9880d681SAndroid Build Coastguard Worker bool isAdd = Imm >= 0;
2393*9880d681SAndroid Build Coastguard Worker if (Imm == INT32_MIN) Imm = 0;
2394*9880d681SAndroid Build Coastguard Worker Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
2395*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Imm));
2396*9880d681SAndroid Build Coastguard Worker }
2397*9880d681SAndroid Build Coastguard Worker
addPostIdxImm8s4Operands(MCInst & Inst,unsigned N) const2398*9880d681SAndroid Build Coastguard Worker void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
2399*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2400*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2401*9880d681SAndroid Build Coastguard Worker assert(CE && "non-constant post-idx-imm8s4 operand!");
2402*9880d681SAndroid Build Coastguard Worker int Imm = CE->getValue();
2403*9880d681SAndroid Build Coastguard Worker bool isAdd = Imm >= 0;
2404*9880d681SAndroid Build Coastguard Worker if (Imm == INT32_MIN) Imm = 0;
2405*9880d681SAndroid Build Coastguard Worker // Immediate is scaled by 4.
2406*9880d681SAndroid Build Coastguard Worker Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
2407*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Imm));
2408*9880d681SAndroid Build Coastguard Worker }
2409*9880d681SAndroid Build Coastguard Worker
addPostIdxRegOperands(MCInst & Inst,unsigned N) const2410*9880d681SAndroid Build Coastguard Worker void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
2411*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2412*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum));
2413*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(PostIdxReg.isAdd));
2414*9880d681SAndroid Build Coastguard Worker }
2415*9880d681SAndroid Build Coastguard Worker
addPostIdxRegShiftedOperands(MCInst & Inst,unsigned N) const2416*9880d681SAndroid Build Coastguard Worker void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
2417*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2418*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum));
2419*9880d681SAndroid Build Coastguard Worker // The sign, shift type, and shift amount are encoded in a single operand
2420*9880d681SAndroid Build Coastguard Worker // using the AM2 encoding helpers.
2421*9880d681SAndroid Build Coastguard Worker ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
2422*9880d681SAndroid Build Coastguard Worker unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
2423*9880d681SAndroid Build Coastguard Worker PostIdxReg.ShiftTy);
2424*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Imm));
2425*9880d681SAndroid Build Coastguard Worker }
2426*9880d681SAndroid Build Coastguard Worker
addMSRMaskOperands(MCInst & Inst,unsigned N) const2427*9880d681SAndroid Build Coastguard Worker void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
2428*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2429*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(unsigned(getMSRMask())));
2430*9880d681SAndroid Build Coastguard Worker }
2431*9880d681SAndroid Build Coastguard Worker
addBankedRegOperands(MCInst & Inst,unsigned N) const2432*9880d681SAndroid Build Coastguard Worker void addBankedRegOperands(MCInst &Inst, unsigned N) const {
2433*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2434*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(unsigned(getBankedReg())));
2435*9880d681SAndroid Build Coastguard Worker }
2436*9880d681SAndroid Build Coastguard Worker
addProcIFlagsOperands(MCInst & Inst,unsigned N) const2437*9880d681SAndroid Build Coastguard Worker void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
2438*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2439*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(unsigned(getProcIFlags())));
2440*9880d681SAndroid Build Coastguard Worker }
2441*9880d681SAndroid Build Coastguard Worker
addVecListOperands(MCInst & Inst,unsigned N) const2442*9880d681SAndroid Build Coastguard Worker void addVecListOperands(MCInst &Inst, unsigned N) const {
2443*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2444*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(VectorList.RegNum));
2445*9880d681SAndroid Build Coastguard Worker }
2446*9880d681SAndroid Build Coastguard Worker
addVecListIndexedOperands(MCInst & Inst,unsigned N) const2447*9880d681SAndroid Build Coastguard Worker void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
2448*9880d681SAndroid Build Coastguard Worker assert(N == 2 && "Invalid number of operands!");
2449*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(VectorList.RegNum));
2450*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(VectorList.LaneIndex));
2451*9880d681SAndroid Build Coastguard Worker }
2452*9880d681SAndroid Build Coastguard Worker
addVectorIndex8Operands(MCInst & Inst,unsigned N) const2453*9880d681SAndroid Build Coastguard Worker void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
2454*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2455*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(getVectorIndex()));
2456*9880d681SAndroid Build Coastguard Worker }
2457*9880d681SAndroid Build Coastguard Worker
addVectorIndex16Operands(MCInst & Inst,unsigned N) const2458*9880d681SAndroid Build Coastguard Worker void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
2459*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2460*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(getVectorIndex()));
2461*9880d681SAndroid Build Coastguard Worker }
2462*9880d681SAndroid Build Coastguard Worker
addVectorIndex32Operands(MCInst & Inst,unsigned N) const2463*9880d681SAndroid Build Coastguard Worker void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
2464*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2465*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(getVectorIndex()));
2466*9880d681SAndroid Build Coastguard Worker }
2467*9880d681SAndroid Build Coastguard Worker
addNEONi8splatOperands(MCInst & Inst,unsigned N) const2468*9880d681SAndroid Build Coastguard Worker void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
2469*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2470*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2471*9880d681SAndroid Build Coastguard Worker // Mask in that this is an i8 splat.
2472*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2473*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(CE->getValue() | 0xe00));
2474*9880d681SAndroid Build Coastguard Worker }
2475*9880d681SAndroid Build Coastguard Worker
addNEONi16splatOperands(MCInst & Inst,unsigned N) const2476*9880d681SAndroid Build Coastguard Worker void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
2477*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2478*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2479*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2480*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
2481*9880d681SAndroid Build Coastguard Worker Value = ARM_AM::encodeNEONi16splat(Value);
2482*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Value));
2483*9880d681SAndroid Build Coastguard Worker }
2484*9880d681SAndroid Build Coastguard Worker
addNEONi16splatNotOperands(MCInst & Inst,unsigned N) const2485*9880d681SAndroid Build Coastguard Worker void addNEONi16splatNotOperands(MCInst &Inst, unsigned N) const {
2486*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2487*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2488*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2489*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
2490*9880d681SAndroid Build Coastguard Worker Value = ARM_AM::encodeNEONi16splat(~Value & 0xffff);
2491*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Value));
2492*9880d681SAndroid Build Coastguard Worker }
2493*9880d681SAndroid Build Coastguard Worker
addNEONi32splatOperands(MCInst & Inst,unsigned N) const2494*9880d681SAndroid Build Coastguard Worker void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
2495*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2496*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2497*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2498*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
2499*9880d681SAndroid Build Coastguard Worker Value = ARM_AM::encodeNEONi32splat(Value);
2500*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Value));
2501*9880d681SAndroid Build Coastguard Worker }
2502*9880d681SAndroid Build Coastguard Worker
addNEONi32splatNotOperands(MCInst & Inst,unsigned N) const2503*9880d681SAndroid Build Coastguard Worker void addNEONi32splatNotOperands(MCInst &Inst, unsigned N) const {
2504*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2505*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2506*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2507*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
2508*9880d681SAndroid Build Coastguard Worker Value = ARM_AM::encodeNEONi32splat(~Value);
2509*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Value));
2510*9880d681SAndroid Build Coastguard Worker }
2511*9880d681SAndroid Build Coastguard Worker
addNEONinvByteReplicateOperands(MCInst & Inst,unsigned N) const2512*9880d681SAndroid Build Coastguard Worker void addNEONinvByteReplicateOperands(MCInst &Inst, unsigned N) const {
2513*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2514*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2515*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2516*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
2517*9880d681SAndroid Build Coastguard Worker assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
2518*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() == ARM::VMOVv16i8) &&
2519*9880d681SAndroid Build Coastguard Worker "All vmvn instructions that wants to replicate non-zero byte "
2520*9880d681SAndroid Build Coastguard Worker "always must be replaced with VMOVv8i8 or VMOVv16i8.");
2521*9880d681SAndroid Build Coastguard Worker unsigned B = ((~Value) & 0xff);
2522*9880d681SAndroid Build Coastguard Worker B |= 0xe00; // cmode = 0b1110
2523*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(B));
2524*9880d681SAndroid Build Coastguard Worker }
addNEONi32vmovOperands(MCInst & Inst,unsigned N) const2525*9880d681SAndroid Build Coastguard Worker void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
2526*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2527*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2528*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2529*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
2530*9880d681SAndroid Build Coastguard Worker if (Value >= 256 && Value <= 0xffff)
2531*9880d681SAndroid Build Coastguard Worker Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2532*9880d681SAndroid Build Coastguard Worker else if (Value > 0xffff && Value <= 0xffffff)
2533*9880d681SAndroid Build Coastguard Worker Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2534*9880d681SAndroid Build Coastguard Worker else if (Value > 0xffffff)
2535*9880d681SAndroid Build Coastguard Worker Value = (Value >> 24) | 0x600;
2536*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Value));
2537*9880d681SAndroid Build Coastguard Worker }
2538*9880d681SAndroid Build Coastguard Worker
addNEONvmovByteReplicateOperands(MCInst & Inst,unsigned N) const2539*9880d681SAndroid Build Coastguard Worker void addNEONvmovByteReplicateOperands(MCInst &Inst, unsigned N) const {
2540*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2541*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2542*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2543*9880d681SAndroid Build Coastguard Worker unsigned Value = CE->getValue();
2544*9880d681SAndroid Build Coastguard Worker assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
2545*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() == ARM::VMOVv16i8) &&
2546*9880d681SAndroid Build Coastguard Worker "All instructions that wants to replicate non-zero byte "
2547*9880d681SAndroid Build Coastguard Worker "always must be replaced with VMOVv8i8 or VMOVv16i8.");
2548*9880d681SAndroid Build Coastguard Worker unsigned B = Value & 0xff;
2549*9880d681SAndroid Build Coastguard Worker B |= 0xe00; // cmode = 0b1110
2550*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(B));
2551*9880d681SAndroid Build Coastguard Worker }
addNEONi32vmovNegOperands(MCInst & Inst,unsigned N) const2552*9880d681SAndroid Build Coastguard Worker void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2553*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2554*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2555*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2556*9880d681SAndroid Build Coastguard Worker unsigned Value = ~CE->getValue();
2557*9880d681SAndroid Build Coastguard Worker if (Value >= 256 && Value <= 0xffff)
2558*9880d681SAndroid Build Coastguard Worker Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2559*9880d681SAndroid Build Coastguard Worker else if (Value > 0xffff && Value <= 0xffffff)
2560*9880d681SAndroid Build Coastguard Worker Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2561*9880d681SAndroid Build Coastguard Worker else if (Value > 0xffffff)
2562*9880d681SAndroid Build Coastguard Worker Value = (Value >> 24) | 0x600;
2563*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Value));
2564*9880d681SAndroid Build Coastguard Worker }
2565*9880d681SAndroid Build Coastguard Worker
addNEONi64splatOperands(MCInst & Inst,unsigned N) const2566*9880d681SAndroid Build Coastguard Worker void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2567*9880d681SAndroid Build Coastguard Worker assert(N == 1 && "Invalid number of operands!");
2568*9880d681SAndroid Build Coastguard Worker // The immediate encodes the type of constant as well as the value.
2569*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2570*9880d681SAndroid Build Coastguard Worker uint64_t Value = CE->getValue();
2571*9880d681SAndroid Build Coastguard Worker unsigned Imm = 0;
2572*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2573*9880d681SAndroid Build Coastguard Worker Imm |= (Value & 1) << i;
2574*9880d681SAndroid Build Coastguard Worker }
2575*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Imm | 0x1e00));
2576*9880d681SAndroid Build Coastguard Worker }
2577*9880d681SAndroid Build Coastguard Worker
2578*9880d681SAndroid Build Coastguard Worker void print(raw_ostream &OS) const override;
2579*9880d681SAndroid Build Coastguard Worker
CreateITMask(unsigned Mask,SMLoc S)2580*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S) {
2581*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_ITCondMask);
2582*9880d681SAndroid Build Coastguard Worker Op->ITMask.Mask = Mask;
2583*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2584*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2585*9880d681SAndroid Build Coastguard Worker return Op;
2586*9880d681SAndroid Build Coastguard Worker }
2587*9880d681SAndroid Build Coastguard Worker
CreateCondCode(ARMCC::CondCodes CC,SMLoc S)2588*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateCondCode(ARMCC::CondCodes CC,
2589*9880d681SAndroid Build Coastguard Worker SMLoc S) {
2590*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_CondCode);
2591*9880d681SAndroid Build Coastguard Worker Op->CC.Val = CC;
2592*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2593*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2594*9880d681SAndroid Build Coastguard Worker return Op;
2595*9880d681SAndroid Build Coastguard Worker }
2596*9880d681SAndroid Build Coastguard Worker
CreateCoprocNum(unsigned CopVal,SMLoc S)2597*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateCoprocNum(unsigned CopVal, SMLoc S) {
2598*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_CoprocNum);
2599*9880d681SAndroid Build Coastguard Worker Op->Cop.Val = CopVal;
2600*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2601*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2602*9880d681SAndroid Build Coastguard Worker return Op;
2603*9880d681SAndroid Build Coastguard Worker }
2604*9880d681SAndroid Build Coastguard Worker
CreateCoprocReg(unsigned CopVal,SMLoc S)2605*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateCoprocReg(unsigned CopVal, SMLoc S) {
2606*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_CoprocReg);
2607*9880d681SAndroid Build Coastguard Worker Op->Cop.Val = CopVal;
2608*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2609*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2610*9880d681SAndroid Build Coastguard Worker return Op;
2611*9880d681SAndroid Build Coastguard Worker }
2612*9880d681SAndroid Build Coastguard Worker
CreateCoprocOption(unsigned Val,SMLoc S,SMLoc E)2613*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateCoprocOption(unsigned Val, SMLoc S,
2614*9880d681SAndroid Build Coastguard Worker SMLoc E) {
2615*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_CoprocOption);
2616*9880d681SAndroid Build Coastguard Worker Op->Cop.Val = Val;
2617*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2618*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2619*9880d681SAndroid Build Coastguard Worker return Op;
2620*9880d681SAndroid Build Coastguard Worker }
2621*9880d681SAndroid Build Coastguard Worker
CreateCCOut(unsigned RegNum,SMLoc S)2622*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateCCOut(unsigned RegNum, SMLoc S) {
2623*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_CCOut);
2624*9880d681SAndroid Build Coastguard Worker Op->Reg.RegNum = RegNum;
2625*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2626*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2627*9880d681SAndroid Build Coastguard Worker return Op;
2628*9880d681SAndroid Build Coastguard Worker }
2629*9880d681SAndroid Build Coastguard Worker
CreateToken(StringRef Str,SMLoc S)2630*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateToken(StringRef Str, SMLoc S) {
2631*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_Token);
2632*9880d681SAndroid Build Coastguard Worker Op->Tok.Data = Str.data();
2633*9880d681SAndroid Build Coastguard Worker Op->Tok.Length = Str.size();
2634*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2635*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2636*9880d681SAndroid Build Coastguard Worker return Op;
2637*9880d681SAndroid Build Coastguard Worker }
2638*9880d681SAndroid Build Coastguard Worker
CreateReg(unsigned RegNum,SMLoc S,SMLoc E)2639*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateReg(unsigned RegNum, SMLoc S,
2640*9880d681SAndroid Build Coastguard Worker SMLoc E) {
2641*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_Register);
2642*9880d681SAndroid Build Coastguard Worker Op->Reg.RegNum = RegNum;
2643*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2644*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2645*9880d681SAndroid Build Coastguard Worker return Op;
2646*9880d681SAndroid Build Coastguard Worker }
2647*9880d681SAndroid Build Coastguard Worker
2648*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,unsigned SrcReg,unsigned ShiftReg,unsigned ShiftImm,SMLoc S,SMLoc E)2649*9880d681SAndroid Build Coastguard Worker CreateShiftedRegister(ARM_AM::ShiftOpc ShTy, unsigned SrcReg,
2650*9880d681SAndroid Build Coastguard Worker unsigned ShiftReg, unsigned ShiftImm, SMLoc S,
2651*9880d681SAndroid Build Coastguard Worker SMLoc E) {
2652*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_ShiftedRegister);
2653*9880d681SAndroid Build Coastguard Worker Op->RegShiftedReg.ShiftTy = ShTy;
2654*9880d681SAndroid Build Coastguard Worker Op->RegShiftedReg.SrcReg = SrcReg;
2655*9880d681SAndroid Build Coastguard Worker Op->RegShiftedReg.ShiftReg = ShiftReg;
2656*9880d681SAndroid Build Coastguard Worker Op->RegShiftedReg.ShiftImm = ShiftImm;
2657*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2658*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2659*9880d681SAndroid Build Coastguard Worker return Op;
2660*9880d681SAndroid Build Coastguard Worker }
2661*9880d681SAndroid Build Coastguard Worker
2662*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,unsigned SrcReg,unsigned ShiftImm,SMLoc S,SMLoc E)2663*9880d681SAndroid Build Coastguard Worker CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy, unsigned SrcReg,
2664*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm, SMLoc S, SMLoc E) {
2665*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_ShiftedImmediate);
2666*9880d681SAndroid Build Coastguard Worker Op->RegShiftedImm.ShiftTy = ShTy;
2667*9880d681SAndroid Build Coastguard Worker Op->RegShiftedImm.SrcReg = SrcReg;
2668*9880d681SAndroid Build Coastguard Worker Op->RegShiftedImm.ShiftImm = ShiftImm;
2669*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2670*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2671*9880d681SAndroid Build Coastguard Worker return Op;
2672*9880d681SAndroid Build Coastguard Worker }
2673*9880d681SAndroid Build Coastguard Worker
CreateShifterImm(bool isASR,unsigned Imm,SMLoc S,SMLoc E)2674*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateShifterImm(bool isASR, unsigned Imm,
2675*9880d681SAndroid Build Coastguard Worker SMLoc S, SMLoc E) {
2676*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_ShifterImmediate);
2677*9880d681SAndroid Build Coastguard Worker Op->ShifterImm.isASR = isASR;
2678*9880d681SAndroid Build Coastguard Worker Op->ShifterImm.Imm = Imm;
2679*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2680*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2681*9880d681SAndroid Build Coastguard Worker return Op;
2682*9880d681SAndroid Build Coastguard Worker }
2683*9880d681SAndroid Build Coastguard Worker
CreateRotImm(unsigned Imm,SMLoc S,SMLoc E)2684*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateRotImm(unsigned Imm, SMLoc S,
2685*9880d681SAndroid Build Coastguard Worker SMLoc E) {
2686*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_RotateImmediate);
2687*9880d681SAndroid Build Coastguard Worker Op->RotImm.Imm = Imm;
2688*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2689*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2690*9880d681SAndroid Build Coastguard Worker return Op;
2691*9880d681SAndroid Build Coastguard Worker }
2692*9880d681SAndroid Build Coastguard Worker
CreateModImm(unsigned Bits,unsigned Rot,SMLoc S,SMLoc E)2693*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateModImm(unsigned Bits, unsigned Rot,
2694*9880d681SAndroid Build Coastguard Worker SMLoc S, SMLoc E) {
2695*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_ModifiedImmediate);
2696*9880d681SAndroid Build Coastguard Worker Op->ModImm.Bits = Bits;
2697*9880d681SAndroid Build Coastguard Worker Op->ModImm.Rot = Rot;
2698*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2699*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2700*9880d681SAndroid Build Coastguard Worker return Op;
2701*9880d681SAndroid Build Coastguard Worker }
2702*9880d681SAndroid Build Coastguard Worker
2703*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateConstantPoolImm(const MCExpr * Val,SMLoc S,SMLoc E)2704*9880d681SAndroid Build Coastguard Worker CreateConstantPoolImm(const MCExpr *Val, SMLoc S, SMLoc E) {
2705*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_ConstantPoolImmediate);
2706*9880d681SAndroid Build Coastguard Worker Op->Imm.Val = Val;
2707*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2708*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2709*9880d681SAndroid Build Coastguard Worker return Op;
2710*9880d681SAndroid Build Coastguard Worker }
2711*9880d681SAndroid Build Coastguard Worker
2712*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateBitfield(unsigned LSB,unsigned Width,SMLoc S,SMLoc E)2713*9880d681SAndroid Build Coastguard Worker CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) {
2714*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_BitfieldDescriptor);
2715*9880d681SAndroid Build Coastguard Worker Op->Bitfield.LSB = LSB;
2716*9880d681SAndroid Build Coastguard Worker Op->Bitfield.Width = Width;
2717*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2718*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2719*9880d681SAndroid Build Coastguard Worker return Op;
2720*9880d681SAndroid Build Coastguard Worker }
2721*9880d681SAndroid Build Coastguard Worker
2722*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateRegList(SmallVectorImpl<std::pair<unsigned,unsigned>> & Regs,SMLoc StartLoc,SMLoc EndLoc)2723*9880d681SAndroid Build Coastguard Worker CreateRegList(SmallVectorImpl<std::pair<unsigned, unsigned>> &Regs,
2724*9880d681SAndroid Build Coastguard Worker SMLoc StartLoc, SMLoc EndLoc) {
2725*9880d681SAndroid Build Coastguard Worker assert (Regs.size() > 0 && "RegList contains no registers?");
2726*9880d681SAndroid Build Coastguard Worker KindTy Kind = k_RegisterList;
2727*9880d681SAndroid Build Coastguard Worker
2728*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().second))
2729*9880d681SAndroid Build Coastguard Worker Kind = k_DPRRegisterList;
2730*9880d681SAndroid Build Coastguard Worker else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
2731*9880d681SAndroid Build Coastguard Worker contains(Regs.front().second))
2732*9880d681SAndroid Build Coastguard Worker Kind = k_SPRRegisterList;
2733*9880d681SAndroid Build Coastguard Worker
2734*9880d681SAndroid Build Coastguard Worker // Sort based on the register encoding values.
2735*9880d681SAndroid Build Coastguard Worker array_pod_sort(Regs.begin(), Regs.end());
2736*9880d681SAndroid Build Coastguard Worker
2737*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(Kind);
2738*9880d681SAndroid Build Coastguard Worker for (SmallVectorImpl<std::pair<unsigned, unsigned> >::const_iterator
2739*9880d681SAndroid Build Coastguard Worker I = Regs.begin(), E = Regs.end(); I != E; ++I)
2740*9880d681SAndroid Build Coastguard Worker Op->Registers.push_back(I->second);
2741*9880d681SAndroid Build Coastguard Worker Op->StartLoc = StartLoc;
2742*9880d681SAndroid Build Coastguard Worker Op->EndLoc = EndLoc;
2743*9880d681SAndroid Build Coastguard Worker return Op;
2744*9880d681SAndroid Build Coastguard Worker }
2745*9880d681SAndroid Build Coastguard Worker
CreateVectorList(unsigned RegNum,unsigned Count,bool isDoubleSpaced,SMLoc S,SMLoc E)2746*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateVectorList(unsigned RegNum,
2747*9880d681SAndroid Build Coastguard Worker unsigned Count,
2748*9880d681SAndroid Build Coastguard Worker bool isDoubleSpaced,
2749*9880d681SAndroid Build Coastguard Worker SMLoc S, SMLoc E) {
2750*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_VectorList);
2751*9880d681SAndroid Build Coastguard Worker Op->VectorList.RegNum = RegNum;
2752*9880d681SAndroid Build Coastguard Worker Op->VectorList.Count = Count;
2753*9880d681SAndroid Build Coastguard Worker Op->VectorList.isDoubleSpaced = isDoubleSpaced;
2754*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2755*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2756*9880d681SAndroid Build Coastguard Worker return Op;
2757*9880d681SAndroid Build Coastguard Worker }
2758*9880d681SAndroid Build Coastguard Worker
2759*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateVectorListAllLanes(unsigned RegNum,unsigned Count,bool isDoubleSpaced,SMLoc S,SMLoc E)2760*9880d681SAndroid Build Coastguard Worker CreateVectorListAllLanes(unsigned RegNum, unsigned Count, bool isDoubleSpaced,
2761*9880d681SAndroid Build Coastguard Worker SMLoc S, SMLoc E) {
2762*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_VectorListAllLanes);
2763*9880d681SAndroid Build Coastguard Worker Op->VectorList.RegNum = RegNum;
2764*9880d681SAndroid Build Coastguard Worker Op->VectorList.Count = Count;
2765*9880d681SAndroid Build Coastguard Worker Op->VectorList.isDoubleSpaced = isDoubleSpaced;
2766*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2767*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2768*9880d681SAndroid Build Coastguard Worker return Op;
2769*9880d681SAndroid Build Coastguard Worker }
2770*9880d681SAndroid Build Coastguard Worker
2771*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateVectorListIndexed(unsigned RegNum,unsigned Count,unsigned Index,bool isDoubleSpaced,SMLoc S,SMLoc E)2772*9880d681SAndroid Build Coastguard Worker CreateVectorListIndexed(unsigned RegNum, unsigned Count, unsigned Index,
2773*9880d681SAndroid Build Coastguard Worker bool isDoubleSpaced, SMLoc S, SMLoc E) {
2774*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_VectorListIndexed);
2775*9880d681SAndroid Build Coastguard Worker Op->VectorList.RegNum = RegNum;
2776*9880d681SAndroid Build Coastguard Worker Op->VectorList.Count = Count;
2777*9880d681SAndroid Build Coastguard Worker Op->VectorList.LaneIndex = Index;
2778*9880d681SAndroid Build Coastguard Worker Op->VectorList.isDoubleSpaced = isDoubleSpaced;
2779*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2780*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2781*9880d681SAndroid Build Coastguard Worker return Op;
2782*9880d681SAndroid Build Coastguard Worker }
2783*9880d681SAndroid Build Coastguard Worker
2784*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateVectorIndex(unsigned Idx,SMLoc S,SMLoc E,MCContext & Ctx)2785*9880d681SAndroid Build Coastguard Worker CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
2786*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_VectorIndex);
2787*9880d681SAndroid Build Coastguard Worker Op->VectorIndex.Val = Idx;
2788*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2789*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2790*9880d681SAndroid Build Coastguard Worker return Op;
2791*9880d681SAndroid Build Coastguard Worker }
2792*9880d681SAndroid Build Coastguard Worker
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E)2793*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateImm(const MCExpr *Val, SMLoc S,
2794*9880d681SAndroid Build Coastguard Worker SMLoc E) {
2795*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_Immediate);
2796*9880d681SAndroid Build Coastguard Worker Op->Imm.Val = Val;
2797*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2798*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2799*9880d681SAndroid Build Coastguard Worker return Op;
2800*9880d681SAndroid Build Coastguard Worker }
2801*9880d681SAndroid Build Coastguard Worker
2802*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateMem(unsigned BaseRegNum,const MCConstantExpr * OffsetImm,unsigned OffsetRegNum,ARM_AM::ShiftOpc ShiftType,unsigned ShiftImm,unsigned Alignment,bool isNegative,SMLoc S,SMLoc E,SMLoc AlignmentLoc=SMLoc ())2803*9880d681SAndroid Build Coastguard Worker CreateMem(unsigned BaseRegNum, const MCConstantExpr *OffsetImm,
2804*9880d681SAndroid Build Coastguard Worker unsigned OffsetRegNum, ARM_AM::ShiftOpc ShiftType,
2805*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm, unsigned Alignment, bool isNegative, SMLoc S,
2806*9880d681SAndroid Build Coastguard Worker SMLoc E, SMLoc AlignmentLoc = SMLoc()) {
2807*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_Memory);
2808*9880d681SAndroid Build Coastguard Worker Op->Memory.BaseRegNum = BaseRegNum;
2809*9880d681SAndroid Build Coastguard Worker Op->Memory.OffsetImm = OffsetImm;
2810*9880d681SAndroid Build Coastguard Worker Op->Memory.OffsetRegNum = OffsetRegNum;
2811*9880d681SAndroid Build Coastguard Worker Op->Memory.ShiftType = ShiftType;
2812*9880d681SAndroid Build Coastguard Worker Op->Memory.ShiftImm = ShiftImm;
2813*9880d681SAndroid Build Coastguard Worker Op->Memory.Alignment = Alignment;
2814*9880d681SAndroid Build Coastguard Worker Op->Memory.isNegative = isNegative;
2815*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2816*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2817*9880d681SAndroid Build Coastguard Worker Op->AlignmentLoc = AlignmentLoc;
2818*9880d681SAndroid Build Coastguard Worker return Op;
2819*9880d681SAndroid Build Coastguard Worker }
2820*9880d681SAndroid Build Coastguard Worker
2821*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreatePostIdxReg(unsigned RegNum,bool isAdd,ARM_AM::ShiftOpc ShiftTy,unsigned ShiftImm,SMLoc S,SMLoc E)2822*9880d681SAndroid Build Coastguard Worker CreatePostIdxReg(unsigned RegNum, bool isAdd, ARM_AM::ShiftOpc ShiftTy,
2823*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm, SMLoc S, SMLoc E) {
2824*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_PostIndexRegister);
2825*9880d681SAndroid Build Coastguard Worker Op->PostIdxReg.RegNum = RegNum;
2826*9880d681SAndroid Build Coastguard Worker Op->PostIdxReg.isAdd = isAdd;
2827*9880d681SAndroid Build Coastguard Worker Op->PostIdxReg.ShiftTy = ShiftTy;
2828*9880d681SAndroid Build Coastguard Worker Op->PostIdxReg.ShiftImm = ShiftImm;
2829*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2830*9880d681SAndroid Build Coastguard Worker Op->EndLoc = E;
2831*9880d681SAndroid Build Coastguard Worker return Op;
2832*9880d681SAndroid Build Coastguard Worker }
2833*9880d681SAndroid Build Coastguard Worker
CreateMemBarrierOpt(ARM_MB::MemBOpt Opt,SMLoc S)2834*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateMemBarrierOpt(ARM_MB::MemBOpt Opt,
2835*9880d681SAndroid Build Coastguard Worker SMLoc S) {
2836*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_MemBarrierOpt);
2837*9880d681SAndroid Build Coastguard Worker Op->MBOpt.Val = Opt;
2838*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2839*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2840*9880d681SAndroid Build Coastguard Worker return Op;
2841*9880d681SAndroid Build Coastguard Worker }
2842*9880d681SAndroid Build Coastguard Worker
2843*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand>
CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt,SMLoc S)2844*9880d681SAndroid Build Coastguard Worker CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S) {
2845*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_InstSyncBarrierOpt);
2846*9880d681SAndroid Build Coastguard Worker Op->ISBOpt.Val = Opt;
2847*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2848*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2849*9880d681SAndroid Build Coastguard Worker return Op;
2850*9880d681SAndroid Build Coastguard Worker }
2851*9880d681SAndroid Build Coastguard Worker
CreateProcIFlags(ARM_PROC::IFlags IFlags,SMLoc S)2852*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateProcIFlags(ARM_PROC::IFlags IFlags,
2853*9880d681SAndroid Build Coastguard Worker SMLoc S) {
2854*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_ProcIFlags);
2855*9880d681SAndroid Build Coastguard Worker Op->IFlags.Val = IFlags;
2856*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2857*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2858*9880d681SAndroid Build Coastguard Worker return Op;
2859*9880d681SAndroid Build Coastguard Worker }
2860*9880d681SAndroid Build Coastguard Worker
CreateMSRMask(unsigned MMask,SMLoc S)2861*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateMSRMask(unsigned MMask, SMLoc S) {
2862*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_MSRMask);
2863*9880d681SAndroid Build Coastguard Worker Op->MMask.Val = MMask;
2864*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2865*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2866*9880d681SAndroid Build Coastguard Worker return Op;
2867*9880d681SAndroid Build Coastguard Worker }
2868*9880d681SAndroid Build Coastguard Worker
CreateBankedReg(unsigned Reg,SMLoc S)2869*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<ARMOperand> CreateBankedReg(unsigned Reg, SMLoc S) {
2870*9880d681SAndroid Build Coastguard Worker auto Op = make_unique<ARMOperand>(k_BankedReg);
2871*9880d681SAndroid Build Coastguard Worker Op->BankedReg.Val = Reg;
2872*9880d681SAndroid Build Coastguard Worker Op->StartLoc = S;
2873*9880d681SAndroid Build Coastguard Worker Op->EndLoc = S;
2874*9880d681SAndroid Build Coastguard Worker return Op;
2875*9880d681SAndroid Build Coastguard Worker }
2876*9880d681SAndroid Build Coastguard Worker };
2877*9880d681SAndroid Build Coastguard Worker
2878*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace.
2879*9880d681SAndroid Build Coastguard Worker
print(raw_ostream & OS) const2880*9880d681SAndroid Build Coastguard Worker void ARMOperand::print(raw_ostream &OS) const {
2881*9880d681SAndroid Build Coastguard Worker switch (Kind) {
2882*9880d681SAndroid Build Coastguard Worker case k_CondCode:
2883*9880d681SAndroid Build Coastguard Worker OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
2884*9880d681SAndroid Build Coastguard Worker break;
2885*9880d681SAndroid Build Coastguard Worker case k_CCOut:
2886*9880d681SAndroid Build Coastguard Worker OS << "<ccout " << getReg() << ">";
2887*9880d681SAndroid Build Coastguard Worker break;
2888*9880d681SAndroid Build Coastguard Worker case k_ITCondMask: {
2889*9880d681SAndroid Build Coastguard Worker static const char *const MaskStr[] = {
2890*9880d681SAndroid Build Coastguard Worker "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2891*9880d681SAndroid Build Coastguard Worker "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2892*9880d681SAndroid Build Coastguard Worker };
2893*9880d681SAndroid Build Coastguard Worker assert((ITMask.Mask & 0xf) == ITMask.Mask);
2894*9880d681SAndroid Build Coastguard Worker OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2895*9880d681SAndroid Build Coastguard Worker break;
2896*9880d681SAndroid Build Coastguard Worker }
2897*9880d681SAndroid Build Coastguard Worker case k_CoprocNum:
2898*9880d681SAndroid Build Coastguard Worker OS << "<coprocessor number: " << getCoproc() << ">";
2899*9880d681SAndroid Build Coastguard Worker break;
2900*9880d681SAndroid Build Coastguard Worker case k_CoprocReg:
2901*9880d681SAndroid Build Coastguard Worker OS << "<coprocessor register: " << getCoproc() << ">";
2902*9880d681SAndroid Build Coastguard Worker break;
2903*9880d681SAndroid Build Coastguard Worker case k_CoprocOption:
2904*9880d681SAndroid Build Coastguard Worker OS << "<coprocessor option: " << CoprocOption.Val << ">";
2905*9880d681SAndroid Build Coastguard Worker break;
2906*9880d681SAndroid Build Coastguard Worker case k_MSRMask:
2907*9880d681SAndroid Build Coastguard Worker OS << "<mask: " << getMSRMask() << ">";
2908*9880d681SAndroid Build Coastguard Worker break;
2909*9880d681SAndroid Build Coastguard Worker case k_BankedReg:
2910*9880d681SAndroid Build Coastguard Worker OS << "<banked reg: " << getBankedReg() << ">";
2911*9880d681SAndroid Build Coastguard Worker break;
2912*9880d681SAndroid Build Coastguard Worker case k_Immediate:
2913*9880d681SAndroid Build Coastguard Worker OS << *getImm();
2914*9880d681SAndroid Build Coastguard Worker break;
2915*9880d681SAndroid Build Coastguard Worker case k_MemBarrierOpt:
2916*9880d681SAndroid Build Coastguard Worker OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt(), false) << ">";
2917*9880d681SAndroid Build Coastguard Worker break;
2918*9880d681SAndroid Build Coastguard Worker case k_InstSyncBarrierOpt:
2919*9880d681SAndroid Build Coastguard Worker OS << "<ARM_ISB::" << InstSyncBOptToString(getInstSyncBarrierOpt()) << ">";
2920*9880d681SAndroid Build Coastguard Worker break;
2921*9880d681SAndroid Build Coastguard Worker case k_Memory:
2922*9880d681SAndroid Build Coastguard Worker OS << "<memory "
2923*9880d681SAndroid Build Coastguard Worker << " base:" << Memory.BaseRegNum;
2924*9880d681SAndroid Build Coastguard Worker OS << ">";
2925*9880d681SAndroid Build Coastguard Worker break;
2926*9880d681SAndroid Build Coastguard Worker case k_PostIndexRegister:
2927*9880d681SAndroid Build Coastguard Worker OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2928*9880d681SAndroid Build Coastguard Worker << PostIdxReg.RegNum;
2929*9880d681SAndroid Build Coastguard Worker if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2930*9880d681SAndroid Build Coastguard Worker OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2931*9880d681SAndroid Build Coastguard Worker << PostIdxReg.ShiftImm;
2932*9880d681SAndroid Build Coastguard Worker OS << ">";
2933*9880d681SAndroid Build Coastguard Worker break;
2934*9880d681SAndroid Build Coastguard Worker case k_ProcIFlags: {
2935*9880d681SAndroid Build Coastguard Worker OS << "<ARM_PROC::";
2936*9880d681SAndroid Build Coastguard Worker unsigned IFlags = getProcIFlags();
2937*9880d681SAndroid Build Coastguard Worker for (int i=2; i >= 0; --i)
2938*9880d681SAndroid Build Coastguard Worker if (IFlags & (1 << i))
2939*9880d681SAndroid Build Coastguard Worker OS << ARM_PROC::IFlagsToString(1 << i);
2940*9880d681SAndroid Build Coastguard Worker OS << ">";
2941*9880d681SAndroid Build Coastguard Worker break;
2942*9880d681SAndroid Build Coastguard Worker }
2943*9880d681SAndroid Build Coastguard Worker case k_Register:
2944*9880d681SAndroid Build Coastguard Worker OS << "<register " << getReg() << ">";
2945*9880d681SAndroid Build Coastguard Worker break;
2946*9880d681SAndroid Build Coastguard Worker case k_ShifterImmediate:
2947*9880d681SAndroid Build Coastguard Worker OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2948*9880d681SAndroid Build Coastguard Worker << " #" << ShifterImm.Imm << ">";
2949*9880d681SAndroid Build Coastguard Worker break;
2950*9880d681SAndroid Build Coastguard Worker case k_ShiftedRegister:
2951*9880d681SAndroid Build Coastguard Worker OS << "<so_reg_reg "
2952*9880d681SAndroid Build Coastguard Worker << RegShiftedReg.SrcReg << " "
2953*9880d681SAndroid Build Coastguard Worker << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2954*9880d681SAndroid Build Coastguard Worker << " " << RegShiftedReg.ShiftReg << ">";
2955*9880d681SAndroid Build Coastguard Worker break;
2956*9880d681SAndroid Build Coastguard Worker case k_ShiftedImmediate:
2957*9880d681SAndroid Build Coastguard Worker OS << "<so_reg_imm "
2958*9880d681SAndroid Build Coastguard Worker << RegShiftedImm.SrcReg << " "
2959*9880d681SAndroid Build Coastguard Worker << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2960*9880d681SAndroid Build Coastguard Worker << " #" << RegShiftedImm.ShiftImm << ">";
2961*9880d681SAndroid Build Coastguard Worker break;
2962*9880d681SAndroid Build Coastguard Worker case k_RotateImmediate:
2963*9880d681SAndroid Build Coastguard Worker OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2964*9880d681SAndroid Build Coastguard Worker break;
2965*9880d681SAndroid Build Coastguard Worker case k_ModifiedImmediate:
2966*9880d681SAndroid Build Coastguard Worker OS << "<mod_imm #" << ModImm.Bits << ", #"
2967*9880d681SAndroid Build Coastguard Worker << ModImm.Rot << ")>";
2968*9880d681SAndroid Build Coastguard Worker break;
2969*9880d681SAndroid Build Coastguard Worker case k_ConstantPoolImmediate:
2970*9880d681SAndroid Build Coastguard Worker OS << "<constant_pool_imm #" << *getConstantPoolImm();
2971*9880d681SAndroid Build Coastguard Worker break;
2972*9880d681SAndroid Build Coastguard Worker case k_BitfieldDescriptor:
2973*9880d681SAndroid Build Coastguard Worker OS << "<bitfield " << "lsb: " << Bitfield.LSB
2974*9880d681SAndroid Build Coastguard Worker << ", width: " << Bitfield.Width << ">";
2975*9880d681SAndroid Build Coastguard Worker break;
2976*9880d681SAndroid Build Coastguard Worker case k_RegisterList:
2977*9880d681SAndroid Build Coastguard Worker case k_DPRRegisterList:
2978*9880d681SAndroid Build Coastguard Worker case k_SPRRegisterList: {
2979*9880d681SAndroid Build Coastguard Worker OS << "<register_list ";
2980*9880d681SAndroid Build Coastguard Worker
2981*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<unsigned> &RegList = getRegList();
2982*9880d681SAndroid Build Coastguard Worker for (SmallVectorImpl<unsigned>::const_iterator
2983*9880d681SAndroid Build Coastguard Worker I = RegList.begin(), E = RegList.end(); I != E; ) {
2984*9880d681SAndroid Build Coastguard Worker OS << *I;
2985*9880d681SAndroid Build Coastguard Worker if (++I < E) OS << ", ";
2986*9880d681SAndroid Build Coastguard Worker }
2987*9880d681SAndroid Build Coastguard Worker
2988*9880d681SAndroid Build Coastguard Worker OS << ">";
2989*9880d681SAndroid Build Coastguard Worker break;
2990*9880d681SAndroid Build Coastguard Worker }
2991*9880d681SAndroid Build Coastguard Worker case k_VectorList:
2992*9880d681SAndroid Build Coastguard Worker OS << "<vector_list " << VectorList.Count << " * "
2993*9880d681SAndroid Build Coastguard Worker << VectorList.RegNum << ">";
2994*9880d681SAndroid Build Coastguard Worker break;
2995*9880d681SAndroid Build Coastguard Worker case k_VectorListAllLanes:
2996*9880d681SAndroid Build Coastguard Worker OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2997*9880d681SAndroid Build Coastguard Worker << VectorList.RegNum << ">";
2998*9880d681SAndroid Build Coastguard Worker break;
2999*9880d681SAndroid Build Coastguard Worker case k_VectorListIndexed:
3000*9880d681SAndroid Build Coastguard Worker OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
3001*9880d681SAndroid Build Coastguard Worker << VectorList.Count << " * " << VectorList.RegNum << ">";
3002*9880d681SAndroid Build Coastguard Worker break;
3003*9880d681SAndroid Build Coastguard Worker case k_Token:
3004*9880d681SAndroid Build Coastguard Worker OS << "'" << getToken() << "'";
3005*9880d681SAndroid Build Coastguard Worker break;
3006*9880d681SAndroid Build Coastguard Worker case k_VectorIndex:
3007*9880d681SAndroid Build Coastguard Worker OS << "<vectorindex " << getVectorIndex() << ">";
3008*9880d681SAndroid Build Coastguard Worker break;
3009*9880d681SAndroid Build Coastguard Worker }
3010*9880d681SAndroid Build Coastguard Worker }
3011*9880d681SAndroid Build Coastguard Worker
3012*9880d681SAndroid Build Coastguard Worker /// @name Auto-generated Match Functions
3013*9880d681SAndroid Build Coastguard Worker /// {
3014*9880d681SAndroid Build Coastguard Worker
3015*9880d681SAndroid Build Coastguard Worker static unsigned MatchRegisterName(StringRef Name);
3016*9880d681SAndroid Build Coastguard Worker
3017*9880d681SAndroid Build Coastguard Worker /// }
3018*9880d681SAndroid Build Coastguard Worker
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)3019*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::ParseRegister(unsigned &RegNo,
3020*9880d681SAndroid Build Coastguard Worker SMLoc &StartLoc, SMLoc &EndLoc) {
3021*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = getParser().getTok();
3022*9880d681SAndroid Build Coastguard Worker StartLoc = Tok.getLoc();
3023*9880d681SAndroid Build Coastguard Worker EndLoc = Tok.getEndLoc();
3024*9880d681SAndroid Build Coastguard Worker RegNo = tryParseRegister();
3025*9880d681SAndroid Build Coastguard Worker
3026*9880d681SAndroid Build Coastguard Worker return (RegNo == (unsigned)-1);
3027*9880d681SAndroid Build Coastguard Worker }
3028*9880d681SAndroid Build Coastguard Worker
3029*9880d681SAndroid Build Coastguard Worker /// Try to parse a register name. The token must be an Identifier when called,
3030*9880d681SAndroid Build Coastguard Worker /// and if it is a register name the token is eaten and the register number is
3031*9880d681SAndroid Build Coastguard Worker /// returned. Otherwise return -1.
3032*9880d681SAndroid Build Coastguard Worker ///
tryParseRegister()3033*9880d681SAndroid Build Coastguard Worker int ARMAsmParser::tryParseRegister() {
3034*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3035*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
3036*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier)) return -1;
3037*9880d681SAndroid Build Coastguard Worker
3038*9880d681SAndroid Build Coastguard Worker std::string lowerCase = Tok.getString().lower();
3039*9880d681SAndroid Build Coastguard Worker unsigned RegNum = MatchRegisterName(lowerCase);
3040*9880d681SAndroid Build Coastguard Worker if (!RegNum) {
3041*9880d681SAndroid Build Coastguard Worker RegNum = StringSwitch<unsigned>(lowerCase)
3042*9880d681SAndroid Build Coastguard Worker .Case("r13", ARM::SP)
3043*9880d681SAndroid Build Coastguard Worker .Case("r14", ARM::LR)
3044*9880d681SAndroid Build Coastguard Worker .Case("r15", ARM::PC)
3045*9880d681SAndroid Build Coastguard Worker .Case("ip", ARM::R12)
3046*9880d681SAndroid Build Coastguard Worker // Additional register name aliases for 'gas' compatibility.
3047*9880d681SAndroid Build Coastguard Worker .Case("a1", ARM::R0)
3048*9880d681SAndroid Build Coastguard Worker .Case("a2", ARM::R1)
3049*9880d681SAndroid Build Coastguard Worker .Case("a3", ARM::R2)
3050*9880d681SAndroid Build Coastguard Worker .Case("a4", ARM::R3)
3051*9880d681SAndroid Build Coastguard Worker .Case("v1", ARM::R4)
3052*9880d681SAndroid Build Coastguard Worker .Case("v2", ARM::R5)
3053*9880d681SAndroid Build Coastguard Worker .Case("v3", ARM::R6)
3054*9880d681SAndroid Build Coastguard Worker .Case("v4", ARM::R7)
3055*9880d681SAndroid Build Coastguard Worker .Case("v5", ARM::R8)
3056*9880d681SAndroid Build Coastguard Worker .Case("v6", ARM::R9)
3057*9880d681SAndroid Build Coastguard Worker .Case("v7", ARM::R10)
3058*9880d681SAndroid Build Coastguard Worker .Case("v8", ARM::R11)
3059*9880d681SAndroid Build Coastguard Worker .Case("sb", ARM::R9)
3060*9880d681SAndroid Build Coastguard Worker .Case("sl", ARM::R10)
3061*9880d681SAndroid Build Coastguard Worker .Case("fp", ARM::R11)
3062*9880d681SAndroid Build Coastguard Worker .Default(0);
3063*9880d681SAndroid Build Coastguard Worker }
3064*9880d681SAndroid Build Coastguard Worker if (!RegNum) {
3065*9880d681SAndroid Build Coastguard Worker // Check for aliases registered via .req. Canonicalize to lower case.
3066*9880d681SAndroid Build Coastguard Worker // That's more consistent since register names are case insensitive, and
3067*9880d681SAndroid Build Coastguard Worker // it's how the original entry was passed in from MC/MCParser/AsmParser.
3068*9880d681SAndroid Build Coastguard Worker StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
3069*9880d681SAndroid Build Coastguard Worker // If no match, return failure.
3070*9880d681SAndroid Build Coastguard Worker if (Entry == RegisterReqs.end())
3071*9880d681SAndroid Build Coastguard Worker return -1;
3072*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
3073*9880d681SAndroid Build Coastguard Worker return Entry->getValue();
3074*9880d681SAndroid Build Coastguard Worker }
3075*9880d681SAndroid Build Coastguard Worker
3076*9880d681SAndroid Build Coastguard Worker // Some FPUs only have 16 D registers, so D16-D31 are invalid
3077*9880d681SAndroid Build Coastguard Worker if (hasD16() && RegNum >= ARM::D16 && RegNum <= ARM::D31)
3078*9880d681SAndroid Build Coastguard Worker return -1;
3079*9880d681SAndroid Build Coastguard Worker
3080*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
3081*9880d681SAndroid Build Coastguard Worker
3082*9880d681SAndroid Build Coastguard Worker return RegNum;
3083*9880d681SAndroid Build Coastguard Worker }
3084*9880d681SAndroid Build Coastguard Worker
3085*9880d681SAndroid Build Coastguard Worker // Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
3086*9880d681SAndroid Build Coastguard Worker // If a recoverable error occurs, return 1. If an irrecoverable error
3087*9880d681SAndroid Build Coastguard Worker // occurs, return -1. An irrecoverable error is one where tokens have been
3088*9880d681SAndroid Build Coastguard Worker // consumed in the process of trying to parse the shifter (i.e., when it is
3089*9880d681SAndroid Build Coastguard Worker // indeed a shifter operand, but malformed).
tryParseShiftRegister(OperandVector & Operands)3090*9880d681SAndroid Build Coastguard Worker int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) {
3091*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3092*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
3093*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
3094*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier))
3095*9880d681SAndroid Build Coastguard Worker return -1;
3096*9880d681SAndroid Build Coastguard Worker
3097*9880d681SAndroid Build Coastguard Worker std::string lowerCase = Tok.getString().lower();
3098*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
3099*9880d681SAndroid Build Coastguard Worker .Case("asl", ARM_AM::lsl)
3100*9880d681SAndroid Build Coastguard Worker .Case("lsl", ARM_AM::lsl)
3101*9880d681SAndroid Build Coastguard Worker .Case("lsr", ARM_AM::lsr)
3102*9880d681SAndroid Build Coastguard Worker .Case("asr", ARM_AM::asr)
3103*9880d681SAndroid Build Coastguard Worker .Case("ror", ARM_AM::ror)
3104*9880d681SAndroid Build Coastguard Worker .Case("rrx", ARM_AM::rrx)
3105*9880d681SAndroid Build Coastguard Worker .Default(ARM_AM::no_shift);
3106*9880d681SAndroid Build Coastguard Worker
3107*9880d681SAndroid Build Coastguard Worker if (ShiftTy == ARM_AM::no_shift)
3108*9880d681SAndroid Build Coastguard Worker return 1;
3109*9880d681SAndroid Build Coastguard Worker
3110*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the operator.
3111*9880d681SAndroid Build Coastguard Worker
3112*9880d681SAndroid Build Coastguard Worker // The source register for the shift has already been added to the
3113*9880d681SAndroid Build Coastguard Worker // operand list, so we need to pop it off and combine it into the shifted
3114*9880d681SAndroid Build Coastguard Worker // register operand instead.
3115*9880d681SAndroid Build Coastguard Worker std::unique_ptr<ARMOperand> PrevOp(
3116*9880d681SAndroid Build Coastguard Worker (ARMOperand *)Operands.pop_back_val().release());
3117*9880d681SAndroid Build Coastguard Worker if (!PrevOp->isReg())
3118*9880d681SAndroid Build Coastguard Worker return Error(PrevOp->getStartLoc(), "shift must be of a register");
3119*9880d681SAndroid Build Coastguard Worker int SrcReg = PrevOp->getReg();
3120*9880d681SAndroid Build Coastguard Worker
3121*9880d681SAndroid Build Coastguard Worker SMLoc EndLoc;
3122*9880d681SAndroid Build Coastguard Worker int64_t Imm = 0;
3123*9880d681SAndroid Build Coastguard Worker int ShiftReg = 0;
3124*9880d681SAndroid Build Coastguard Worker if (ShiftTy == ARM_AM::rrx) {
3125*9880d681SAndroid Build Coastguard Worker // RRX Doesn't have an explicit shift amount. The encoder expects
3126*9880d681SAndroid Build Coastguard Worker // the shift register to be the same as the source register. Seems odd,
3127*9880d681SAndroid Build Coastguard Worker // but OK.
3128*9880d681SAndroid Build Coastguard Worker ShiftReg = SrcReg;
3129*9880d681SAndroid Build Coastguard Worker } else {
3130*9880d681SAndroid Build Coastguard Worker // Figure out if this is shifted by a constant or a register (for non-RRX).
3131*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Hash) ||
3132*9880d681SAndroid Build Coastguard Worker Parser.getTok().is(AsmToken::Dollar)) {
3133*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat hash.
3134*9880d681SAndroid Build Coastguard Worker SMLoc ImmLoc = Parser.getTok().getLoc();
3135*9880d681SAndroid Build Coastguard Worker const MCExpr *ShiftExpr = nullptr;
3136*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(ShiftExpr, EndLoc)) {
3137*9880d681SAndroid Build Coastguard Worker Error(ImmLoc, "invalid immediate shift value");
3138*9880d681SAndroid Build Coastguard Worker return -1;
3139*9880d681SAndroid Build Coastguard Worker }
3140*9880d681SAndroid Build Coastguard Worker // The expression must be evaluatable as an immediate.
3141*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
3142*9880d681SAndroid Build Coastguard Worker if (!CE) {
3143*9880d681SAndroid Build Coastguard Worker Error(ImmLoc, "invalid immediate shift value");
3144*9880d681SAndroid Build Coastguard Worker return -1;
3145*9880d681SAndroid Build Coastguard Worker }
3146*9880d681SAndroid Build Coastguard Worker // Range check the immediate.
3147*9880d681SAndroid Build Coastguard Worker // lsl, ror: 0 <= imm <= 31
3148*9880d681SAndroid Build Coastguard Worker // lsr, asr: 0 <= imm <= 32
3149*9880d681SAndroid Build Coastguard Worker Imm = CE->getValue();
3150*9880d681SAndroid Build Coastguard Worker if (Imm < 0 ||
3151*9880d681SAndroid Build Coastguard Worker ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
3152*9880d681SAndroid Build Coastguard Worker ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
3153*9880d681SAndroid Build Coastguard Worker Error(ImmLoc, "immediate shift value out of range");
3154*9880d681SAndroid Build Coastguard Worker return -1;
3155*9880d681SAndroid Build Coastguard Worker }
3156*9880d681SAndroid Build Coastguard Worker // shift by zero is a nop. Always send it through as lsl.
3157*9880d681SAndroid Build Coastguard Worker // ('as' compatibility)
3158*9880d681SAndroid Build Coastguard Worker if (Imm == 0)
3159*9880d681SAndroid Build Coastguard Worker ShiftTy = ARM_AM::lsl;
3160*9880d681SAndroid Build Coastguard Worker } else if (Parser.getTok().is(AsmToken::Identifier)) {
3161*9880d681SAndroid Build Coastguard Worker SMLoc L = Parser.getTok().getLoc();
3162*9880d681SAndroid Build Coastguard Worker EndLoc = Parser.getTok().getEndLoc();
3163*9880d681SAndroid Build Coastguard Worker ShiftReg = tryParseRegister();
3164*9880d681SAndroid Build Coastguard Worker if (ShiftReg == -1) {
3165*9880d681SAndroid Build Coastguard Worker Error(L, "expected immediate or register in shift operand");
3166*9880d681SAndroid Build Coastguard Worker return -1;
3167*9880d681SAndroid Build Coastguard Worker }
3168*9880d681SAndroid Build Coastguard Worker } else {
3169*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(),
3170*9880d681SAndroid Build Coastguard Worker "expected immediate or register in shift operand");
3171*9880d681SAndroid Build Coastguard Worker return -1;
3172*9880d681SAndroid Build Coastguard Worker }
3173*9880d681SAndroid Build Coastguard Worker }
3174*9880d681SAndroid Build Coastguard Worker
3175*9880d681SAndroid Build Coastguard Worker if (ShiftReg && ShiftTy != ARM_AM::rrx)
3176*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
3177*9880d681SAndroid Build Coastguard Worker ShiftReg, Imm,
3178*9880d681SAndroid Build Coastguard Worker S, EndLoc));
3179*9880d681SAndroid Build Coastguard Worker else
3180*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
3181*9880d681SAndroid Build Coastguard Worker S, EndLoc));
3182*9880d681SAndroid Build Coastguard Worker
3183*9880d681SAndroid Build Coastguard Worker return 0;
3184*9880d681SAndroid Build Coastguard Worker }
3185*9880d681SAndroid Build Coastguard Worker
3186*9880d681SAndroid Build Coastguard Worker
3187*9880d681SAndroid Build Coastguard Worker /// Try to parse a register name. The token must be an Identifier when called.
3188*9880d681SAndroid Build Coastguard Worker /// If it's a register, an AsmOperand is created. Another AsmOperand is created
3189*9880d681SAndroid Build Coastguard Worker /// if there is a "writeback". 'true' if it's not a register.
3190*9880d681SAndroid Build Coastguard Worker ///
3191*9880d681SAndroid Build Coastguard Worker /// TODO this is likely to change to allow different register types and or to
3192*9880d681SAndroid Build Coastguard Worker /// parse for a specific register type.
tryParseRegisterWithWriteBack(OperandVector & Operands)3193*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) {
3194*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3195*9880d681SAndroid Build Coastguard Worker const AsmToken &RegTok = Parser.getTok();
3196*9880d681SAndroid Build Coastguard Worker int RegNo = tryParseRegister();
3197*9880d681SAndroid Build Coastguard Worker if (RegNo == -1)
3198*9880d681SAndroid Build Coastguard Worker return true;
3199*9880d681SAndroid Build Coastguard Worker
3200*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateReg(RegNo, RegTok.getLoc(),
3201*9880d681SAndroid Build Coastguard Worker RegTok.getEndLoc()));
3202*9880d681SAndroid Build Coastguard Worker
3203*9880d681SAndroid Build Coastguard Worker const AsmToken &ExclaimTok = Parser.getTok();
3204*9880d681SAndroid Build Coastguard Worker if (ExclaimTok.is(AsmToken::Exclaim)) {
3205*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
3206*9880d681SAndroid Build Coastguard Worker ExclaimTok.getLoc()));
3207*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat exclaim token
3208*9880d681SAndroid Build Coastguard Worker return false;
3209*9880d681SAndroid Build Coastguard Worker }
3210*9880d681SAndroid Build Coastguard Worker
3211*9880d681SAndroid Build Coastguard Worker // Also check for an index operand. This is only legal for vector registers,
3212*9880d681SAndroid Build Coastguard Worker // but that'll get caught OK in operand matching, so we don't need to
3213*9880d681SAndroid Build Coastguard Worker // explicitly filter everything else out here.
3214*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::LBrac)) {
3215*9880d681SAndroid Build Coastguard Worker SMLoc SIdx = Parser.getTok().getLoc();
3216*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat left bracket token.
3217*9880d681SAndroid Build Coastguard Worker
3218*9880d681SAndroid Build Coastguard Worker const MCExpr *ImmVal;
3219*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(ImmVal))
3220*9880d681SAndroid Build Coastguard Worker return true;
3221*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3222*9880d681SAndroid Build Coastguard Worker if (!MCE)
3223*9880d681SAndroid Build Coastguard Worker return TokError("immediate value expected for vector index");
3224*9880d681SAndroid Build Coastguard Worker
3225*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::RBrac))
3226*9880d681SAndroid Build Coastguard Worker return Error(Parser.getTok().getLoc(), "']' expected");
3227*9880d681SAndroid Build Coastguard Worker
3228*9880d681SAndroid Build Coastguard Worker SMLoc E = Parser.getTok().getEndLoc();
3229*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat right bracket token.
3230*9880d681SAndroid Build Coastguard Worker
3231*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
3232*9880d681SAndroid Build Coastguard Worker SIdx, E,
3233*9880d681SAndroid Build Coastguard Worker getContext()));
3234*9880d681SAndroid Build Coastguard Worker }
3235*9880d681SAndroid Build Coastguard Worker
3236*9880d681SAndroid Build Coastguard Worker return false;
3237*9880d681SAndroid Build Coastguard Worker }
3238*9880d681SAndroid Build Coastguard Worker
3239*9880d681SAndroid Build Coastguard Worker /// MatchCoprocessorOperandName - Try to parse an coprocessor related
3240*9880d681SAndroid Build Coastguard Worker /// instruction with a symbolic operand name.
3241*9880d681SAndroid Build Coastguard Worker /// We accept "crN" syntax for GAS compatibility.
3242*9880d681SAndroid Build Coastguard Worker /// <operand-name> ::= <prefix><number>
3243*9880d681SAndroid Build Coastguard Worker /// If CoprocOp is 'c', then:
3244*9880d681SAndroid Build Coastguard Worker /// <prefix> ::= c | cr
3245*9880d681SAndroid Build Coastguard Worker /// If CoprocOp is 'p', then :
3246*9880d681SAndroid Build Coastguard Worker /// <prefix> ::= p
3247*9880d681SAndroid Build Coastguard Worker /// <number> ::= integer in range [0, 15]
MatchCoprocessorOperandName(StringRef Name,char CoprocOp)3248*9880d681SAndroid Build Coastguard Worker static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
3249*9880d681SAndroid Build Coastguard Worker // Use the same layout as the tablegen'erated register name matcher. Ugly,
3250*9880d681SAndroid Build Coastguard Worker // but efficient.
3251*9880d681SAndroid Build Coastguard Worker if (Name.size() < 2 || Name[0] != CoprocOp)
3252*9880d681SAndroid Build Coastguard Worker return -1;
3253*9880d681SAndroid Build Coastguard Worker Name = (Name[1] == 'r') ? Name.drop_front(2) : Name.drop_front();
3254*9880d681SAndroid Build Coastguard Worker
3255*9880d681SAndroid Build Coastguard Worker switch (Name.size()) {
3256*9880d681SAndroid Build Coastguard Worker default: return -1;
3257*9880d681SAndroid Build Coastguard Worker case 1:
3258*9880d681SAndroid Build Coastguard Worker switch (Name[0]) {
3259*9880d681SAndroid Build Coastguard Worker default: return -1;
3260*9880d681SAndroid Build Coastguard Worker case '0': return 0;
3261*9880d681SAndroid Build Coastguard Worker case '1': return 1;
3262*9880d681SAndroid Build Coastguard Worker case '2': return 2;
3263*9880d681SAndroid Build Coastguard Worker case '3': return 3;
3264*9880d681SAndroid Build Coastguard Worker case '4': return 4;
3265*9880d681SAndroid Build Coastguard Worker case '5': return 5;
3266*9880d681SAndroid Build Coastguard Worker case '6': return 6;
3267*9880d681SAndroid Build Coastguard Worker case '7': return 7;
3268*9880d681SAndroid Build Coastguard Worker case '8': return 8;
3269*9880d681SAndroid Build Coastguard Worker case '9': return 9;
3270*9880d681SAndroid Build Coastguard Worker }
3271*9880d681SAndroid Build Coastguard Worker case 2:
3272*9880d681SAndroid Build Coastguard Worker if (Name[0] != '1')
3273*9880d681SAndroid Build Coastguard Worker return -1;
3274*9880d681SAndroid Build Coastguard Worker switch (Name[1]) {
3275*9880d681SAndroid Build Coastguard Worker default: return -1;
3276*9880d681SAndroid Build Coastguard Worker // CP10 and CP11 are VFP/NEON and so vector instructions should be used.
3277*9880d681SAndroid Build Coastguard Worker // However, old cores (v5/v6) did use them in that way.
3278*9880d681SAndroid Build Coastguard Worker case '0': return 10;
3279*9880d681SAndroid Build Coastguard Worker case '1': return 11;
3280*9880d681SAndroid Build Coastguard Worker case '2': return 12;
3281*9880d681SAndroid Build Coastguard Worker case '3': return 13;
3282*9880d681SAndroid Build Coastguard Worker case '4': return 14;
3283*9880d681SAndroid Build Coastguard Worker case '5': return 15;
3284*9880d681SAndroid Build Coastguard Worker }
3285*9880d681SAndroid Build Coastguard Worker }
3286*9880d681SAndroid Build Coastguard Worker }
3287*9880d681SAndroid Build Coastguard Worker
3288*9880d681SAndroid Build Coastguard Worker /// parseITCondCode - Try to parse a condition code for an IT instruction.
3289*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseITCondCode(OperandVector & Operands)3290*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseITCondCode(OperandVector &Operands) {
3291*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3292*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
3293*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
3294*9880d681SAndroid Build Coastguard Worker if (!Tok.is(AsmToken::Identifier))
3295*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3296*9880d681SAndroid Build Coastguard Worker unsigned CC = StringSwitch<unsigned>(Tok.getString().lower())
3297*9880d681SAndroid Build Coastguard Worker .Case("eq", ARMCC::EQ)
3298*9880d681SAndroid Build Coastguard Worker .Case("ne", ARMCC::NE)
3299*9880d681SAndroid Build Coastguard Worker .Case("hs", ARMCC::HS)
3300*9880d681SAndroid Build Coastguard Worker .Case("cs", ARMCC::HS)
3301*9880d681SAndroid Build Coastguard Worker .Case("lo", ARMCC::LO)
3302*9880d681SAndroid Build Coastguard Worker .Case("cc", ARMCC::LO)
3303*9880d681SAndroid Build Coastguard Worker .Case("mi", ARMCC::MI)
3304*9880d681SAndroid Build Coastguard Worker .Case("pl", ARMCC::PL)
3305*9880d681SAndroid Build Coastguard Worker .Case("vs", ARMCC::VS)
3306*9880d681SAndroid Build Coastguard Worker .Case("vc", ARMCC::VC)
3307*9880d681SAndroid Build Coastguard Worker .Case("hi", ARMCC::HI)
3308*9880d681SAndroid Build Coastguard Worker .Case("ls", ARMCC::LS)
3309*9880d681SAndroid Build Coastguard Worker .Case("ge", ARMCC::GE)
3310*9880d681SAndroid Build Coastguard Worker .Case("lt", ARMCC::LT)
3311*9880d681SAndroid Build Coastguard Worker .Case("gt", ARMCC::GT)
3312*9880d681SAndroid Build Coastguard Worker .Case("le", ARMCC::LE)
3313*9880d681SAndroid Build Coastguard Worker .Case("al", ARMCC::AL)
3314*9880d681SAndroid Build Coastguard Worker .Default(~0U);
3315*9880d681SAndroid Build Coastguard Worker if (CC == ~0U)
3316*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3317*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the token.
3318*9880d681SAndroid Build Coastguard Worker
3319*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
3320*9880d681SAndroid Build Coastguard Worker
3321*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3322*9880d681SAndroid Build Coastguard Worker }
3323*9880d681SAndroid Build Coastguard Worker
3324*9880d681SAndroid Build Coastguard Worker /// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
3325*9880d681SAndroid Build Coastguard Worker /// token must be an Identifier when called, and if it is a coprocessor
3326*9880d681SAndroid Build Coastguard Worker /// number, the token is eaten and the operand is added to the operand list.
3327*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseCoprocNumOperand(OperandVector & Operands)3328*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) {
3329*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3330*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
3331*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
3332*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier))
3333*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3334*9880d681SAndroid Build Coastguard Worker
3335*9880d681SAndroid Build Coastguard Worker int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
3336*9880d681SAndroid Build Coastguard Worker if (Num == -1)
3337*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3338*9880d681SAndroid Build Coastguard Worker // ARMv7 and v8 don't allow cp10/cp11 due to VFP/NEON specific instructions
3339*9880d681SAndroid Build Coastguard Worker if ((hasV7Ops() || hasV8Ops()) && (Num == 10 || Num == 11))
3340*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3341*9880d681SAndroid Build Coastguard Worker
3342*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
3343*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
3344*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3345*9880d681SAndroid Build Coastguard Worker }
3346*9880d681SAndroid Build Coastguard Worker
3347*9880d681SAndroid Build Coastguard Worker /// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
3348*9880d681SAndroid Build Coastguard Worker /// token must be an Identifier when called, and if it is a coprocessor
3349*9880d681SAndroid Build Coastguard Worker /// number, the token is eaten and the operand is added to the operand list.
3350*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseCoprocRegOperand(OperandVector & Operands)3351*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) {
3352*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3353*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
3354*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
3355*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier))
3356*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3357*9880d681SAndroid Build Coastguard Worker
3358*9880d681SAndroid Build Coastguard Worker int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
3359*9880d681SAndroid Build Coastguard Worker if (Reg == -1)
3360*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3361*9880d681SAndroid Build Coastguard Worker
3362*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
3363*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
3364*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3365*9880d681SAndroid Build Coastguard Worker }
3366*9880d681SAndroid Build Coastguard Worker
3367*9880d681SAndroid Build Coastguard Worker /// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
3368*9880d681SAndroid Build Coastguard Worker /// coproc_option : '{' imm0_255 '}'
3369*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseCoprocOptionOperand(OperandVector & Operands)3370*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseCoprocOptionOperand(OperandVector &Operands) {
3371*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3372*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
3373*9880d681SAndroid Build Coastguard Worker
3374*9880d681SAndroid Build Coastguard Worker // If this isn't a '{', this isn't a coprocessor immediate operand.
3375*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::LCurly))
3376*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3377*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '{'
3378*9880d681SAndroid Build Coastguard Worker
3379*9880d681SAndroid Build Coastguard Worker const MCExpr *Expr;
3380*9880d681SAndroid Build Coastguard Worker SMLoc Loc = Parser.getTok().getLoc();
3381*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Expr)) {
3382*9880d681SAndroid Build Coastguard Worker Error(Loc, "illegal expression");
3383*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3384*9880d681SAndroid Build Coastguard Worker }
3385*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3386*9880d681SAndroid Build Coastguard Worker if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
3387*9880d681SAndroid Build Coastguard Worker Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
3388*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3389*9880d681SAndroid Build Coastguard Worker }
3390*9880d681SAndroid Build Coastguard Worker int Val = CE->getValue();
3391*9880d681SAndroid Build Coastguard Worker
3392*9880d681SAndroid Build Coastguard Worker // Check for and consume the closing '}'
3393*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::RCurly))
3394*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3395*9880d681SAndroid Build Coastguard Worker SMLoc E = Parser.getTok().getEndLoc();
3396*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '}'
3397*9880d681SAndroid Build Coastguard Worker
3398*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
3399*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3400*9880d681SAndroid Build Coastguard Worker }
3401*9880d681SAndroid Build Coastguard Worker
3402*9880d681SAndroid Build Coastguard Worker // For register list parsing, we need to map from raw GPR register numbering
3403*9880d681SAndroid Build Coastguard Worker // to the enumeration values. The enumeration values aren't sorted by
3404*9880d681SAndroid Build Coastguard Worker // register number due to our using "sp", "lr" and "pc" as canonical names.
getNextRegister(unsigned Reg)3405*9880d681SAndroid Build Coastguard Worker static unsigned getNextRegister(unsigned Reg) {
3406*9880d681SAndroid Build Coastguard Worker // If this is a GPR, we need to do it manually, otherwise we can rely
3407*9880d681SAndroid Build Coastguard Worker // on the sort ordering of the enumeration since the other reg-classes
3408*9880d681SAndroid Build Coastguard Worker // are sane.
3409*9880d681SAndroid Build Coastguard Worker if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
3410*9880d681SAndroid Build Coastguard Worker return Reg + 1;
3411*9880d681SAndroid Build Coastguard Worker switch(Reg) {
3412*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Invalid GPR number!");
3413*9880d681SAndroid Build Coastguard Worker case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
3414*9880d681SAndroid Build Coastguard Worker case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
3415*9880d681SAndroid Build Coastguard Worker case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
3416*9880d681SAndroid Build Coastguard Worker case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
3417*9880d681SAndroid Build Coastguard Worker case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
3418*9880d681SAndroid Build Coastguard Worker case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
3419*9880d681SAndroid Build Coastguard Worker case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
3420*9880d681SAndroid Build Coastguard Worker case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
3421*9880d681SAndroid Build Coastguard Worker }
3422*9880d681SAndroid Build Coastguard Worker }
3423*9880d681SAndroid Build Coastguard Worker
3424*9880d681SAndroid Build Coastguard Worker // Return the low-subreg of a given Q register.
getDRegFromQReg(unsigned QReg)3425*9880d681SAndroid Build Coastguard Worker static unsigned getDRegFromQReg(unsigned QReg) {
3426*9880d681SAndroid Build Coastguard Worker switch (QReg) {
3427*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("expected a Q register!");
3428*9880d681SAndroid Build Coastguard Worker case ARM::Q0: return ARM::D0;
3429*9880d681SAndroid Build Coastguard Worker case ARM::Q1: return ARM::D2;
3430*9880d681SAndroid Build Coastguard Worker case ARM::Q2: return ARM::D4;
3431*9880d681SAndroid Build Coastguard Worker case ARM::Q3: return ARM::D6;
3432*9880d681SAndroid Build Coastguard Worker case ARM::Q4: return ARM::D8;
3433*9880d681SAndroid Build Coastguard Worker case ARM::Q5: return ARM::D10;
3434*9880d681SAndroid Build Coastguard Worker case ARM::Q6: return ARM::D12;
3435*9880d681SAndroid Build Coastguard Worker case ARM::Q7: return ARM::D14;
3436*9880d681SAndroid Build Coastguard Worker case ARM::Q8: return ARM::D16;
3437*9880d681SAndroid Build Coastguard Worker case ARM::Q9: return ARM::D18;
3438*9880d681SAndroid Build Coastguard Worker case ARM::Q10: return ARM::D20;
3439*9880d681SAndroid Build Coastguard Worker case ARM::Q11: return ARM::D22;
3440*9880d681SAndroid Build Coastguard Worker case ARM::Q12: return ARM::D24;
3441*9880d681SAndroid Build Coastguard Worker case ARM::Q13: return ARM::D26;
3442*9880d681SAndroid Build Coastguard Worker case ARM::Q14: return ARM::D28;
3443*9880d681SAndroid Build Coastguard Worker case ARM::Q15: return ARM::D30;
3444*9880d681SAndroid Build Coastguard Worker }
3445*9880d681SAndroid Build Coastguard Worker }
3446*9880d681SAndroid Build Coastguard Worker
3447*9880d681SAndroid Build Coastguard Worker /// Parse a register list.
parseRegisterList(OperandVector & Operands)3448*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseRegisterList(OperandVector &Operands) {
3449*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3450*9880d681SAndroid Build Coastguard Worker assert(Parser.getTok().is(AsmToken::LCurly) &&
3451*9880d681SAndroid Build Coastguard Worker "Token is not a Left Curly Brace");
3452*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
3453*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '{' token.
3454*9880d681SAndroid Build Coastguard Worker SMLoc RegLoc = Parser.getTok().getLoc();
3455*9880d681SAndroid Build Coastguard Worker
3456*9880d681SAndroid Build Coastguard Worker // Check the first register in the list to see what register class
3457*9880d681SAndroid Build Coastguard Worker // this is a list of.
3458*9880d681SAndroid Build Coastguard Worker int Reg = tryParseRegister();
3459*9880d681SAndroid Build Coastguard Worker if (Reg == -1)
3460*9880d681SAndroid Build Coastguard Worker return Error(RegLoc, "register expected");
3461*9880d681SAndroid Build Coastguard Worker
3462*9880d681SAndroid Build Coastguard Worker // The reglist instructions have at most 16 registers, so reserve
3463*9880d681SAndroid Build Coastguard Worker // space for that many.
3464*9880d681SAndroid Build Coastguard Worker int EReg = 0;
3465*9880d681SAndroid Build Coastguard Worker SmallVector<std::pair<unsigned, unsigned>, 16> Registers;
3466*9880d681SAndroid Build Coastguard Worker
3467*9880d681SAndroid Build Coastguard Worker // Allow Q regs and just interpret them as the two D sub-registers.
3468*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3469*9880d681SAndroid Build Coastguard Worker Reg = getDRegFromQReg(Reg);
3470*9880d681SAndroid Build Coastguard Worker EReg = MRI->getEncodingValue(Reg);
3471*9880d681SAndroid Build Coastguard Worker Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3472*9880d681SAndroid Build Coastguard Worker ++Reg;
3473*9880d681SAndroid Build Coastguard Worker }
3474*9880d681SAndroid Build Coastguard Worker const MCRegisterClass *RC;
3475*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
3476*9880d681SAndroid Build Coastguard Worker RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
3477*9880d681SAndroid Build Coastguard Worker else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
3478*9880d681SAndroid Build Coastguard Worker RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
3479*9880d681SAndroid Build Coastguard Worker else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
3480*9880d681SAndroid Build Coastguard Worker RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
3481*9880d681SAndroid Build Coastguard Worker else
3482*9880d681SAndroid Build Coastguard Worker return Error(RegLoc, "invalid register in register list");
3483*9880d681SAndroid Build Coastguard Worker
3484*9880d681SAndroid Build Coastguard Worker // Store the register.
3485*9880d681SAndroid Build Coastguard Worker EReg = MRI->getEncodingValue(Reg);
3486*9880d681SAndroid Build Coastguard Worker Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3487*9880d681SAndroid Build Coastguard Worker
3488*9880d681SAndroid Build Coastguard Worker // This starts immediately after the first register token in the list,
3489*9880d681SAndroid Build Coastguard Worker // so we can see either a comma or a minus (range separator) as a legal
3490*9880d681SAndroid Build Coastguard Worker // next token.
3491*9880d681SAndroid Build Coastguard Worker while (Parser.getTok().is(AsmToken::Comma) ||
3492*9880d681SAndroid Build Coastguard Worker Parser.getTok().is(AsmToken::Minus)) {
3493*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Minus)) {
3494*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the minus.
3495*9880d681SAndroid Build Coastguard Worker SMLoc AfterMinusLoc = Parser.getTok().getLoc();
3496*9880d681SAndroid Build Coastguard Worker int EndReg = tryParseRegister();
3497*9880d681SAndroid Build Coastguard Worker if (EndReg == -1)
3498*9880d681SAndroid Build Coastguard Worker return Error(AfterMinusLoc, "register expected");
3499*9880d681SAndroid Build Coastguard Worker // Allow Q regs and just interpret them as the two D sub-registers.
3500*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3501*9880d681SAndroid Build Coastguard Worker EndReg = getDRegFromQReg(EndReg) + 1;
3502*9880d681SAndroid Build Coastguard Worker // If the register is the same as the start reg, there's nothing
3503*9880d681SAndroid Build Coastguard Worker // more to do.
3504*9880d681SAndroid Build Coastguard Worker if (Reg == EndReg)
3505*9880d681SAndroid Build Coastguard Worker continue;
3506*9880d681SAndroid Build Coastguard Worker // The register must be in the same register class as the first.
3507*9880d681SAndroid Build Coastguard Worker if (!RC->contains(EndReg))
3508*9880d681SAndroid Build Coastguard Worker return Error(AfterMinusLoc, "invalid register in register list");
3509*9880d681SAndroid Build Coastguard Worker // Ranges must go from low to high.
3510*9880d681SAndroid Build Coastguard Worker if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg))
3511*9880d681SAndroid Build Coastguard Worker return Error(AfterMinusLoc, "bad range in register list");
3512*9880d681SAndroid Build Coastguard Worker
3513*9880d681SAndroid Build Coastguard Worker // Add all the registers in the range to the register list.
3514*9880d681SAndroid Build Coastguard Worker while (Reg != EndReg) {
3515*9880d681SAndroid Build Coastguard Worker Reg = getNextRegister(Reg);
3516*9880d681SAndroid Build Coastguard Worker EReg = MRI->getEncodingValue(Reg);
3517*9880d681SAndroid Build Coastguard Worker Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3518*9880d681SAndroid Build Coastguard Worker }
3519*9880d681SAndroid Build Coastguard Worker continue;
3520*9880d681SAndroid Build Coastguard Worker }
3521*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the comma.
3522*9880d681SAndroid Build Coastguard Worker RegLoc = Parser.getTok().getLoc();
3523*9880d681SAndroid Build Coastguard Worker int OldReg = Reg;
3524*9880d681SAndroid Build Coastguard Worker const AsmToken RegTok = Parser.getTok();
3525*9880d681SAndroid Build Coastguard Worker Reg = tryParseRegister();
3526*9880d681SAndroid Build Coastguard Worker if (Reg == -1)
3527*9880d681SAndroid Build Coastguard Worker return Error(RegLoc, "register expected");
3528*9880d681SAndroid Build Coastguard Worker // Allow Q regs and just interpret them as the two D sub-registers.
3529*9880d681SAndroid Build Coastguard Worker bool isQReg = false;
3530*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3531*9880d681SAndroid Build Coastguard Worker Reg = getDRegFromQReg(Reg);
3532*9880d681SAndroid Build Coastguard Worker isQReg = true;
3533*9880d681SAndroid Build Coastguard Worker }
3534*9880d681SAndroid Build Coastguard Worker // The register must be in the same register class as the first.
3535*9880d681SAndroid Build Coastguard Worker if (!RC->contains(Reg))
3536*9880d681SAndroid Build Coastguard Worker return Error(RegLoc, "invalid register in register list");
3537*9880d681SAndroid Build Coastguard Worker // List must be monotonically increasing.
3538*9880d681SAndroid Build Coastguard Worker if (MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) {
3539*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
3540*9880d681SAndroid Build Coastguard Worker Warning(RegLoc, "register list not in ascending order");
3541*9880d681SAndroid Build Coastguard Worker else
3542*9880d681SAndroid Build Coastguard Worker return Error(RegLoc, "register list not in ascending order");
3543*9880d681SAndroid Build Coastguard Worker }
3544*9880d681SAndroid Build Coastguard Worker if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) {
3545*9880d681SAndroid Build Coastguard Worker Warning(RegLoc, "duplicated register (" + RegTok.getString() +
3546*9880d681SAndroid Build Coastguard Worker ") in register list");
3547*9880d681SAndroid Build Coastguard Worker continue;
3548*9880d681SAndroid Build Coastguard Worker }
3549*9880d681SAndroid Build Coastguard Worker // VFP register lists must also be contiguous.
3550*9880d681SAndroid Build Coastguard Worker if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
3551*9880d681SAndroid Build Coastguard Worker Reg != OldReg + 1)
3552*9880d681SAndroid Build Coastguard Worker return Error(RegLoc, "non-contiguous register range");
3553*9880d681SAndroid Build Coastguard Worker EReg = MRI->getEncodingValue(Reg);
3554*9880d681SAndroid Build Coastguard Worker Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3555*9880d681SAndroid Build Coastguard Worker if (isQReg) {
3556*9880d681SAndroid Build Coastguard Worker EReg = MRI->getEncodingValue(++Reg);
3557*9880d681SAndroid Build Coastguard Worker Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3558*9880d681SAndroid Build Coastguard Worker }
3559*9880d681SAndroid Build Coastguard Worker }
3560*9880d681SAndroid Build Coastguard Worker
3561*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::RCurly))
3562*9880d681SAndroid Build Coastguard Worker return Error(Parser.getTok().getLoc(), "'}' expected");
3563*9880d681SAndroid Build Coastguard Worker SMLoc E = Parser.getTok().getEndLoc();
3564*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '}' token.
3565*9880d681SAndroid Build Coastguard Worker
3566*9880d681SAndroid Build Coastguard Worker // Push the register list operand.
3567*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
3568*9880d681SAndroid Build Coastguard Worker
3569*9880d681SAndroid Build Coastguard Worker // The ARM system instruction variants for LDM/STM have a '^' token here.
3570*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Caret)) {
3571*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
3572*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '^' token.
3573*9880d681SAndroid Build Coastguard Worker }
3574*9880d681SAndroid Build Coastguard Worker
3575*9880d681SAndroid Build Coastguard Worker return false;
3576*9880d681SAndroid Build Coastguard Worker }
3577*9880d681SAndroid Build Coastguard Worker
3578*9880d681SAndroid Build Coastguard Worker // Helper function to parse the lane index for vector lists.
3579*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy ARMAsmParser::
parseVectorLane(VectorLaneTy & LaneKind,unsigned & Index,SMLoc & EndLoc)3580*9880d681SAndroid Build Coastguard Worker parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) {
3581*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3582*9880d681SAndroid Build Coastguard Worker Index = 0; // Always return a defined index value.
3583*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::LBrac)) {
3584*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '['.
3585*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::RBrac)) {
3586*9880d681SAndroid Build Coastguard Worker // "Dn[]" is the 'all lanes' syntax.
3587*9880d681SAndroid Build Coastguard Worker LaneKind = AllLanes;
3588*9880d681SAndroid Build Coastguard Worker EndLoc = Parser.getTok().getEndLoc();
3589*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the ']'.
3590*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3591*9880d681SAndroid Build Coastguard Worker }
3592*9880d681SAndroid Build Coastguard Worker
3593*9880d681SAndroid Build Coastguard Worker // There's an optional '#' token here. Normally there wouldn't be, but
3594*9880d681SAndroid Build Coastguard Worker // inline assemble puts one in, and it's friendly to accept that.
3595*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Hash))
3596*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '#' or '$'.
3597*9880d681SAndroid Build Coastguard Worker
3598*9880d681SAndroid Build Coastguard Worker const MCExpr *LaneIndex;
3599*9880d681SAndroid Build Coastguard Worker SMLoc Loc = Parser.getTok().getLoc();
3600*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(LaneIndex)) {
3601*9880d681SAndroid Build Coastguard Worker Error(Loc, "illegal expression");
3602*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3603*9880d681SAndroid Build Coastguard Worker }
3604*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
3605*9880d681SAndroid Build Coastguard Worker if (!CE) {
3606*9880d681SAndroid Build Coastguard Worker Error(Loc, "lane index must be empty or an integer");
3607*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3608*9880d681SAndroid Build Coastguard Worker }
3609*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::RBrac)) {
3610*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "']' expected");
3611*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3612*9880d681SAndroid Build Coastguard Worker }
3613*9880d681SAndroid Build Coastguard Worker EndLoc = Parser.getTok().getEndLoc();
3614*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the ']'.
3615*9880d681SAndroid Build Coastguard Worker int64_t Val = CE->getValue();
3616*9880d681SAndroid Build Coastguard Worker
3617*9880d681SAndroid Build Coastguard Worker // FIXME: Make this range check context sensitive for .8, .16, .32.
3618*9880d681SAndroid Build Coastguard Worker if (Val < 0 || Val > 7) {
3619*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "lane index out of range");
3620*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3621*9880d681SAndroid Build Coastguard Worker }
3622*9880d681SAndroid Build Coastguard Worker Index = Val;
3623*9880d681SAndroid Build Coastguard Worker LaneKind = IndexedLane;
3624*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3625*9880d681SAndroid Build Coastguard Worker }
3626*9880d681SAndroid Build Coastguard Worker LaneKind = NoLanes;
3627*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3628*9880d681SAndroid Build Coastguard Worker }
3629*9880d681SAndroid Build Coastguard Worker
3630*9880d681SAndroid Build Coastguard Worker // parse a vector register list
3631*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseVectorList(OperandVector & Operands)3632*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseVectorList(OperandVector &Operands) {
3633*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3634*9880d681SAndroid Build Coastguard Worker VectorLaneTy LaneKind;
3635*9880d681SAndroid Build Coastguard Worker unsigned LaneIndex;
3636*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
3637*9880d681SAndroid Build Coastguard Worker // As an extension (to match gas), support a plain D register or Q register
3638*9880d681SAndroid Build Coastguard Worker // (without encosing curly braces) as a single or double entry list,
3639*9880d681SAndroid Build Coastguard Worker // respectively.
3640*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Identifier)) {
3641*9880d681SAndroid Build Coastguard Worker SMLoc E = Parser.getTok().getEndLoc();
3642*9880d681SAndroid Build Coastguard Worker int Reg = tryParseRegister();
3643*9880d681SAndroid Build Coastguard Worker if (Reg == -1)
3644*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3645*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
3646*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E);
3647*9880d681SAndroid Build Coastguard Worker if (Res != MatchOperand_Success)
3648*9880d681SAndroid Build Coastguard Worker return Res;
3649*9880d681SAndroid Build Coastguard Worker switch (LaneKind) {
3650*9880d681SAndroid Build Coastguard Worker case NoLanes:
3651*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
3652*9880d681SAndroid Build Coastguard Worker break;
3653*9880d681SAndroid Build Coastguard Worker case AllLanes:
3654*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3655*9880d681SAndroid Build Coastguard Worker S, E));
3656*9880d681SAndroid Build Coastguard Worker break;
3657*9880d681SAndroid Build Coastguard Worker case IndexedLane:
3658*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
3659*9880d681SAndroid Build Coastguard Worker LaneIndex,
3660*9880d681SAndroid Build Coastguard Worker false, S, E));
3661*9880d681SAndroid Build Coastguard Worker break;
3662*9880d681SAndroid Build Coastguard Worker }
3663*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3664*9880d681SAndroid Build Coastguard Worker }
3665*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3666*9880d681SAndroid Build Coastguard Worker Reg = getDRegFromQReg(Reg);
3667*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E);
3668*9880d681SAndroid Build Coastguard Worker if (Res != MatchOperand_Success)
3669*9880d681SAndroid Build Coastguard Worker return Res;
3670*9880d681SAndroid Build Coastguard Worker switch (LaneKind) {
3671*9880d681SAndroid Build Coastguard Worker case NoLanes:
3672*9880d681SAndroid Build Coastguard Worker Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3673*9880d681SAndroid Build Coastguard Worker &ARMMCRegisterClasses[ARM::DPairRegClassID]);
3674*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
3675*9880d681SAndroid Build Coastguard Worker break;
3676*9880d681SAndroid Build Coastguard Worker case AllLanes:
3677*9880d681SAndroid Build Coastguard Worker Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3678*9880d681SAndroid Build Coastguard Worker &ARMMCRegisterClasses[ARM::DPairRegClassID]);
3679*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3680*9880d681SAndroid Build Coastguard Worker S, E));
3681*9880d681SAndroid Build Coastguard Worker break;
3682*9880d681SAndroid Build Coastguard Worker case IndexedLane:
3683*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
3684*9880d681SAndroid Build Coastguard Worker LaneIndex,
3685*9880d681SAndroid Build Coastguard Worker false, S, E));
3686*9880d681SAndroid Build Coastguard Worker break;
3687*9880d681SAndroid Build Coastguard Worker }
3688*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3689*9880d681SAndroid Build Coastguard Worker }
3690*9880d681SAndroid Build Coastguard Worker Error(S, "vector register expected");
3691*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3692*9880d681SAndroid Build Coastguard Worker }
3693*9880d681SAndroid Build Coastguard Worker
3694*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::LCurly))
3695*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3696*9880d681SAndroid Build Coastguard Worker
3697*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '{' token.
3698*9880d681SAndroid Build Coastguard Worker SMLoc RegLoc = Parser.getTok().getLoc();
3699*9880d681SAndroid Build Coastguard Worker
3700*9880d681SAndroid Build Coastguard Worker int Reg = tryParseRegister();
3701*9880d681SAndroid Build Coastguard Worker if (Reg == -1) {
3702*9880d681SAndroid Build Coastguard Worker Error(RegLoc, "register expected");
3703*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3704*9880d681SAndroid Build Coastguard Worker }
3705*9880d681SAndroid Build Coastguard Worker unsigned Count = 1;
3706*9880d681SAndroid Build Coastguard Worker int Spacing = 0;
3707*9880d681SAndroid Build Coastguard Worker unsigned FirstReg = Reg;
3708*9880d681SAndroid Build Coastguard Worker // The list is of D registers, but we also allow Q regs and just interpret
3709*9880d681SAndroid Build Coastguard Worker // them as the two D sub-registers.
3710*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3711*9880d681SAndroid Build Coastguard Worker FirstReg = Reg = getDRegFromQReg(Reg);
3712*9880d681SAndroid Build Coastguard Worker Spacing = 1; // double-spacing requires explicit D registers, otherwise
3713*9880d681SAndroid Build Coastguard Worker // it's ambiguous with four-register single spaced.
3714*9880d681SAndroid Build Coastguard Worker ++Reg;
3715*9880d681SAndroid Build Coastguard Worker ++Count;
3716*9880d681SAndroid Build Coastguard Worker }
3717*9880d681SAndroid Build Coastguard Worker
3718*9880d681SAndroid Build Coastguard Worker SMLoc E;
3719*9880d681SAndroid Build Coastguard Worker if (parseVectorLane(LaneKind, LaneIndex, E) != MatchOperand_Success)
3720*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3721*9880d681SAndroid Build Coastguard Worker
3722*9880d681SAndroid Build Coastguard Worker while (Parser.getTok().is(AsmToken::Comma) ||
3723*9880d681SAndroid Build Coastguard Worker Parser.getTok().is(AsmToken::Minus)) {
3724*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Minus)) {
3725*9880d681SAndroid Build Coastguard Worker if (!Spacing)
3726*9880d681SAndroid Build Coastguard Worker Spacing = 1; // Register range implies a single spaced list.
3727*9880d681SAndroid Build Coastguard Worker else if (Spacing == 2) {
3728*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(),
3729*9880d681SAndroid Build Coastguard Worker "sequential registers in double spaced list");
3730*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3731*9880d681SAndroid Build Coastguard Worker }
3732*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the minus.
3733*9880d681SAndroid Build Coastguard Worker SMLoc AfterMinusLoc = Parser.getTok().getLoc();
3734*9880d681SAndroid Build Coastguard Worker int EndReg = tryParseRegister();
3735*9880d681SAndroid Build Coastguard Worker if (EndReg == -1) {
3736*9880d681SAndroid Build Coastguard Worker Error(AfterMinusLoc, "register expected");
3737*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3738*9880d681SAndroid Build Coastguard Worker }
3739*9880d681SAndroid Build Coastguard Worker // Allow Q regs and just interpret them as the two D sub-registers.
3740*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3741*9880d681SAndroid Build Coastguard Worker EndReg = getDRegFromQReg(EndReg) + 1;
3742*9880d681SAndroid Build Coastguard Worker // If the register is the same as the start reg, there's nothing
3743*9880d681SAndroid Build Coastguard Worker // more to do.
3744*9880d681SAndroid Build Coastguard Worker if (Reg == EndReg)
3745*9880d681SAndroid Build Coastguard Worker continue;
3746*9880d681SAndroid Build Coastguard Worker // The register must be in the same register class as the first.
3747*9880d681SAndroid Build Coastguard Worker if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3748*9880d681SAndroid Build Coastguard Worker Error(AfterMinusLoc, "invalid register in register list");
3749*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3750*9880d681SAndroid Build Coastguard Worker }
3751*9880d681SAndroid Build Coastguard Worker // Ranges must go from low to high.
3752*9880d681SAndroid Build Coastguard Worker if (Reg > EndReg) {
3753*9880d681SAndroid Build Coastguard Worker Error(AfterMinusLoc, "bad range in register list");
3754*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3755*9880d681SAndroid Build Coastguard Worker }
3756*9880d681SAndroid Build Coastguard Worker // Parse the lane specifier if present.
3757*9880d681SAndroid Build Coastguard Worker VectorLaneTy NextLaneKind;
3758*9880d681SAndroid Build Coastguard Worker unsigned NextLaneIndex;
3759*9880d681SAndroid Build Coastguard Worker if (parseVectorLane(NextLaneKind, NextLaneIndex, E) !=
3760*9880d681SAndroid Build Coastguard Worker MatchOperand_Success)
3761*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3762*9880d681SAndroid Build Coastguard Worker if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
3763*9880d681SAndroid Build Coastguard Worker Error(AfterMinusLoc, "mismatched lane index in register list");
3764*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3765*9880d681SAndroid Build Coastguard Worker }
3766*9880d681SAndroid Build Coastguard Worker
3767*9880d681SAndroid Build Coastguard Worker // Add all the registers in the range to the register list.
3768*9880d681SAndroid Build Coastguard Worker Count += EndReg - Reg;
3769*9880d681SAndroid Build Coastguard Worker Reg = EndReg;
3770*9880d681SAndroid Build Coastguard Worker continue;
3771*9880d681SAndroid Build Coastguard Worker }
3772*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the comma.
3773*9880d681SAndroid Build Coastguard Worker RegLoc = Parser.getTok().getLoc();
3774*9880d681SAndroid Build Coastguard Worker int OldReg = Reg;
3775*9880d681SAndroid Build Coastguard Worker Reg = tryParseRegister();
3776*9880d681SAndroid Build Coastguard Worker if (Reg == -1) {
3777*9880d681SAndroid Build Coastguard Worker Error(RegLoc, "register expected");
3778*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3779*9880d681SAndroid Build Coastguard Worker }
3780*9880d681SAndroid Build Coastguard Worker // vector register lists must be contiguous.
3781*9880d681SAndroid Build Coastguard Worker // It's OK to use the enumeration values directly here rather, as the
3782*9880d681SAndroid Build Coastguard Worker // VFP register classes have the enum sorted properly.
3783*9880d681SAndroid Build Coastguard Worker //
3784*9880d681SAndroid Build Coastguard Worker // The list is of D registers, but we also allow Q regs and just interpret
3785*9880d681SAndroid Build Coastguard Worker // them as the two D sub-registers.
3786*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3787*9880d681SAndroid Build Coastguard Worker if (!Spacing)
3788*9880d681SAndroid Build Coastguard Worker Spacing = 1; // Register range implies a single spaced list.
3789*9880d681SAndroid Build Coastguard Worker else if (Spacing == 2) {
3790*9880d681SAndroid Build Coastguard Worker Error(RegLoc,
3791*9880d681SAndroid Build Coastguard Worker "invalid register in double-spaced list (must be 'D' register')");
3792*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3793*9880d681SAndroid Build Coastguard Worker }
3794*9880d681SAndroid Build Coastguard Worker Reg = getDRegFromQReg(Reg);
3795*9880d681SAndroid Build Coastguard Worker if (Reg != OldReg + 1) {
3796*9880d681SAndroid Build Coastguard Worker Error(RegLoc, "non-contiguous register range");
3797*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3798*9880d681SAndroid Build Coastguard Worker }
3799*9880d681SAndroid Build Coastguard Worker ++Reg;
3800*9880d681SAndroid Build Coastguard Worker Count += 2;
3801*9880d681SAndroid Build Coastguard Worker // Parse the lane specifier if present.
3802*9880d681SAndroid Build Coastguard Worker VectorLaneTy NextLaneKind;
3803*9880d681SAndroid Build Coastguard Worker unsigned NextLaneIndex;
3804*9880d681SAndroid Build Coastguard Worker SMLoc LaneLoc = Parser.getTok().getLoc();
3805*9880d681SAndroid Build Coastguard Worker if (parseVectorLane(NextLaneKind, NextLaneIndex, E) !=
3806*9880d681SAndroid Build Coastguard Worker MatchOperand_Success)
3807*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3808*9880d681SAndroid Build Coastguard Worker if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
3809*9880d681SAndroid Build Coastguard Worker Error(LaneLoc, "mismatched lane index in register list");
3810*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3811*9880d681SAndroid Build Coastguard Worker }
3812*9880d681SAndroid Build Coastguard Worker continue;
3813*9880d681SAndroid Build Coastguard Worker }
3814*9880d681SAndroid Build Coastguard Worker // Normal D register.
3815*9880d681SAndroid Build Coastguard Worker // Figure out the register spacing (single or double) of the list if
3816*9880d681SAndroid Build Coastguard Worker // we don't know it already.
3817*9880d681SAndroid Build Coastguard Worker if (!Spacing)
3818*9880d681SAndroid Build Coastguard Worker Spacing = 1 + (Reg == OldReg + 2);
3819*9880d681SAndroid Build Coastguard Worker
3820*9880d681SAndroid Build Coastguard Worker // Just check that it's contiguous and keep going.
3821*9880d681SAndroid Build Coastguard Worker if (Reg != OldReg + Spacing) {
3822*9880d681SAndroid Build Coastguard Worker Error(RegLoc, "non-contiguous register range");
3823*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3824*9880d681SAndroid Build Coastguard Worker }
3825*9880d681SAndroid Build Coastguard Worker ++Count;
3826*9880d681SAndroid Build Coastguard Worker // Parse the lane specifier if present.
3827*9880d681SAndroid Build Coastguard Worker VectorLaneTy NextLaneKind;
3828*9880d681SAndroid Build Coastguard Worker unsigned NextLaneIndex;
3829*9880d681SAndroid Build Coastguard Worker SMLoc EndLoc = Parser.getTok().getLoc();
3830*9880d681SAndroid Build Coastguard Worker if (parseVectorLane(NextLaneKind, NextLaneIndex, E) != MatchOperand_Success)
3831*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3832*9880d681SAndroid Build Coastguard Worker if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
3833*9880d681SAndroid Build Coastguard Worker Error(EndLoc, "mismatched lane index in register list");
3834*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3835*9880d681SAndroid Build Coastguard Worker }
3836*9880d681SAndroid Build Coastguard Worker }
3837*9880d681SAndroid Build Coastguard Worker
3838*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::RCurly)) {
3839*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "'}' expected");
3840*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3841*9880d681SAndroid Build Coastguard Worker }
3842*9880d681SAndroid Build Coastguard Worker E = Parser.getTok().getEndLoc();
3843*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '}' token.
3844*9880d681SAndroid Build Coastguard Worker
3845*9880d681SAndroid Build Coastguard Worker switch (LaneKind) {
3846*9880d681SAndroid Build Coastguard Worker case NoLanes:
3847*9880d681SAndroid Build Coastguard Worker // Two-register operands have been converted to the
3848*9880d681SAndroid Build Coastguard Worker // composite register classes.
3849*9880d681SAndroid Build Coastguard Worker if (Count == 2) {
3850*9880d681SAndroid Build Coastguard Worker const MCRegisterClass *RC = (Spacing == 1) ?
3851*9880d681SAndroid Build Coastguard Worker &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3852*9880d681SAndroid Build Coastguard Worker &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3853*9880d681SAndroid Build Coastguard Worker FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3854*9880d681SAndroid Build Coastguard Worker }
3855*9880d681SAndroid Build Coastguard Worker
3856*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3857*9880d681SAndroid Build Coastguard Worker (Spacing == 2), S, E));
3858*9880d681SAndroid Build Coastguard Worker break;
3859*9880d681SAndroid Build Coastguard Worker case AllLanes:
3860*9880d681SAndroid Build Coastguard Worker // Two-register operands have been converted to the
3861*9880d681SAndroid Build Coastguard Worker // composite register classes.
3862*9880d681SAndroid Build Coastguard Worker if (Count == 2) {
3863*9880d681SAndroid Build Coastguard Worker const MCRegisterClass *RC = (Spacing == 1) ?
3864*9880d681SAndroid Build Coastguard Worker &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3865*9880d681SAndroid Build Coastguard Worker &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3866*9880d681SAndroid Build Coastguard Worker FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3867*9880d681SAndroid Build Coastguard Worker }
3868*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
3869*9880d681SAndroid Build Coastguard Worker (Spacing == 2),
3870*9880d681SAndroid Build Coastguard Worker S, E));
3871*9880d681SAndroid Build Coastguard Worker break;
3872*9880d681SAndroid Build Coastguard Worker case IndexedLane:
3873*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
3874*9880d681SAndroid Build Coastguard Worker LaneIndex,
3875*9880d681SAndroid Build Coastguard Worker (Spacing == 2),
3876*9880d681SAndroid Build Coastguard Worker S, E));
3877*9880d681SAndroid Build Coastguard Worker break;
3878*9880d681SAndroid Build Coastguard Worker }
3879*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3880*9880d681SAndroid Build Coastguard Worker }
3881*9880d681SAndroid Build Coastguard Worker
3882*9880d681SAndroid Build Coastguard Worker /// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
3883*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseMemBarrierOptOperand(OperandVector & Operands)3884*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) {
3885*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3886*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
3887*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
3888*9880d681SAndroid Build Coastguard Worker unsigned Opt;
3889*9880d681SAndroid Build Coastguard Worker
3890*9880d681SAndroid Build Coastguard Worker if (Tok.is(AsmToken::Identifier)) {
3891*9880d681SAndroid Build Coastguard Worker StringRef OptStr = Tok.getString();
3892*9880d681SAndroid Build Coastguard Worker
3893*9880d681SAndroid Build Coastguard Worker Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()).lower())
3894*9880d681SAndroid Build Coastguard Worker .Case("sy", ARM_MB::SY)
3895*9880d681SAndroid Build Coastguard Worker .Case("st", ARM_MB::ST)
3896*9880d681SAndroid Build Coastguard Worker .Case("ld", ARM_MB::LD)
3897*9880d681SAndroid Build Coastguard Worker .Case("sh", ARM_MB::ISH)
3898*9880d681SAndroid Build Coastguard Worker .Case("ish", ARM_MB::ISH)
3899*9880d681SAndroid Build Coastguard Worker .Case("shst", ARM_MB::ISHST)
3900*9880d681SAndroid Build Coastguard Worker .Case("ishst", ARM_MB::ISHST)
3901*9880d681SAndroid Build Coastguard Worker .Case("ishld", ARM_MB::ISHLD)
3902*9880d681SAndroid Build Coastguard Worker .Case("nsh", ARM_MB::NSH)
3903*9880d681SAndroid Build Coastguard Worker .Case("un", ARM_MB::NSH)
3904*9880d681SAndroid Build Coastguard Worker .Case("nshst", ARM_MB::NSHST)
3905*9880d681SAndroid Build Coastguard Worker .Case("nshld", ARM_MB::NSHLD)
3906*9880d681SAndroid Build Coastguard Worker .Case("unst", ARM_MB::NSHST)
3907*9880d681SAndroid Build Coastguard Worker .Case("osh", ARM_MB::OSH)
3908*9880d681SAndroid Build Coastguard Worker .Case("oshst", ARM_MB::OSHST)
3909*9880d681SAndroid Build Coastguard Worker .Case("oshld", ARM_MB::OSHLD)
3910*9880d681SAndroid Build Coastguard Worker .Default(~0U);
3911*9880d681SAndroid Build Coastguard Worker
3912*9880d681SAndroid Build Coastguard Worker // ishld, oshld, nshld and ld are only available from ARMv8.
3913*9880d681SAndroid Build Coastguard Worker if (!hasV8Ops() && (Opt == ARM_MB::ISHLD || Opt == ARM_MB::OSHLD ||
3914*9880d681SAndroid Build Coastguard Worker Opt == ARM_MB::NSHLD || Opt == ARM_MB::LD))
3915*9880d681SAndroid Build Coastguard Worker Opt = ~0U;
3916*9880d681SAndroid Build Coastguard Worker
3917*9880d681SAndroid Build Coastguard Worker if (Opt == ~0U)
3918*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3919*9880d681SAndroid Build Coastguard Worker
3920*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
3921*9880d681SAndroid Build Coastguard Worker } else if (Tok.is(AsmToken::Hash) ||
3922*9880d681SAndroid Build Coastguard Worker Tok.is(AsmToken::Dollar) ||
3923*9880d681SAndroid Build Coastguard Worker Tok.is(AsmToken::Integer)) {
3924*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Integer))
3925*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '#' or '$'.
3926*9880d681SAndroid Build Coastguard Worker SMLoc Loc = Parser.getTok().getLoc();
3927*9880d681SAndroid Build Coastguard Worker
3928*9880d681SAndroid Build Coastguard Worker const MCExpr *MemBarrierID;
3929*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(MemBarrierID)) {
3930*9880d681SAndroid Build Coastguard Worker Error(Loc, "illegal expression");
3931*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3932*9880d681SAndroid Build Coastguard Worker }
3933*9880d681SAndroid Build Coastguard Worker
3934*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(MemBarrierID);
3935*9880d681SAndroid Build Coastguard Worker if (!CE) {
3936*9880d681SAndroid Build Coastguard Worker Error(Loc, "constant expression expected");
3937*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3938*9880d681SAndroid Build Coastguard Worker }
3939*9880d681SAndroid Build Coastguard Worker
3940*9880d681SAndroid Build Coastguard Worker int Val = CE->getValue();
3941*9880d681SAndroid Build Coastguard Worker if (Val & ~0xf) {
3942*9880d681SAndroid Build Coastguard Worker Error(Loc, "immediate value out of range");
3943*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3944*9880d681SAndroid Build Coastguard Worker }
3945*9880d681SAndroid Build Coastguard Worker
3946*9880d681SAndroid Build Coastguard Worker Opt = ARM_MB::RESERVED_0 + Val;
3947*9880d681SAndroid Build Coastguard Worker } else
3948*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3949*9880d681SAndroid Build Coastguard Worker
3950*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
3951*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
3952*9880d681SAndroid Build Coastguard Worker }
3953*9880d681SAndroid Build Coastguard Worker
3954*9880d681SAndroid Build Coastguard Worker /// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options.
3955*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseInstSyncBarrierOptOperand(OperandVector & Operands)3956*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) {
3957*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
3958*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
3959*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
3960*9880d681SAndroid Build Coastguard Worker unsigned Opt;
3961*9880d681SAndroid Build Coastguard Worker
3962*9880d681SAndroid Build Coastguard Worker if (Tok.is(AsmToken::Identifier)) {
3963*9880d681SAndroid Build Coastguard Worker StringRef OptStr = Tok.getString();
3964*9880d681SAndroid Build Coastguard Worker
3965*9880d681SAndroid Build Coastguard Worker if (OptStr.equals_lower("sy"))
3966*9880d681SAndroid Build Coastguard Worker Opt = ARM_ISB::SY;
3967*9880d681SAndroid Build Coastguard Worker else
3968*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
3969*9880d681SAndroid Build Coastguard Worker
3970*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
3971*9880d681SAndroid Build Coastguard Worker } else if (Tok.is(AsmToken::Hash) ||
3972*9880d681SAndroid Build Coastguard Worker Tok.is(AsmToken::Dollar) ||
3973*9880d681SAndroid Build Coastguard Worker Tok.is(AsmToken::Integer)) {
3974*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Integer))
3975*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '#' or '$'.
3976*9880d681SAndroid Build Coastguard Worker SMLoc Loc = Parser.getTok().getLoc();
3977*9880d681SAndroid Build Coastguard Worker
3978*9880d681SAndroid Build Coastguard Worker const MCExpr *ISBarrierID;
3979*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(ISBarrierID)) {
3980*9880d681SAndroid Build Coastguard Worker Error(Loc, "illegal expression");
3981*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3982*9880d681SAndroid Build Coastguard Worker }
3983*9880d681SAndroid Build Coastguard Worker
3984*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ISBarrierID);
3985*9880d681SAndroid Build Coastguard Worker if (!CE) {
3986*9880d681SAndroid Build Coastguard Worker Error(Loc, "constant expression expected");
3987*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3988*9880d681SAndroid Build Coastguard Worker }
3989*9880d681SAndroid Build Coastguard Worker
3990*9880d681SAndroid Build Coastguard Worker int Val = CE->getValue();
3991*9880d681SAndroid Build Coastguard Worker if (Val & ~0xf) {
3992*9880d681SAndroid Build Coastguard Worker Error(Loc, "immediate value out of range");
3993*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3994*9880d681SAndroid Build Coastguard Worker }
3995*9880d681SAndroid Build Coastguard Worker
3996*9880d681SAndroid Build Coastguard Worker Opt = ARM_ISB::RESERVED_0 + Val;
3997*9880d681SAndroid Build Coastguard Worker } else
3998*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
3999*9880d681SAndroid Build Coastguard Worker
4000*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt(
4001*9880d681SAndroid Build Coastguard Worker (ARM_ISB::InstSyncBOpt)Opt, S));
4002*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4003*9880d681SAndroid Build Coastguard Worker }
4004*9880d681SAndroid Build Coastguard Worker
4005*9880d681SAndroid Build Coastguard Worker
4006*9880d681SAndroid Build Coastguard Worker /// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
4007*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseProcIFlagsOperand(OperandVector & Operands)4008*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) {
4009*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4010*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
4011*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
4012*9880d681SAndroid Build Coastguard Worker if (!Tok.is(AsmToken::Identifier))
4013*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4014*9880d681SAndroid Build Coastguard Worker StringRef IFlagsStr = Tok.getString();
4015*9880d681SAndroid Build Coastguard Worker
4016*9880d681SAndroid Build Coastguard Worker // An iflags string of "none" is interpreted to mean that none of the AIF
4017*9880d681SAndroid Build Coastguard Worker // bits are set. Not a terribly useful instruction, but a valid encoding.
4018*9880d681SAndroid Build Coastguard Worker unsigned IFlags = 0;
4019*9880d681SAndroid Build Coastguard Worker if (IFlagsStr != "none") {
4020*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
4021*9880d681SAndroid Build Coastguard Worker unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
4022*9880d681SAndroid Build Coastguard Worker .Case("a", ARM_PROC::A)
4023*9880d681SAndroid Build Coastguard Worker .Case("i", ARM_PROC::I)
4024*9880d681SAndroid Build Coastguard Worker .Case("f", ARM_PROC::F)
4025*9880d681SAndroid Build Coastguard Worker .Default(~0U);
4026*9880d681SAndroid Build Coastguard Worker
4027*9880d681SAndroid Build Coastguard Worker // If some specific iflag is already set, it means that some letter is
4028*9880d681SAndroid Build Coastguard Worker // present more than once, this is not acceptable.
4029*9880d681SAndroid Build Coastguard Worker if (Flag == ~0U || (IFlags & Flag))
4030*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4031*9880d681SAndroid Build Coastguard Worker
4032*9880d681SAndroid Build Coastguard Worker IFlags |= Flag;
4033*9880d681SAndroid Build Coastguard Worker }
4034*9880d681SAndroid Build Coastguard Worker }
4035*9880d681SAndroid Build Coastguard Worker
4036*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
4037*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
4038*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4039*9880d681SAndroid Build Coastguard Worker }
4040*9880d681SAndroid Build Coastguard Worker
4041*9880d681SAndroid Build Coastguard Worker /// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
4042*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseMSRMaskOperand(OperandVector & Operands)4043*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) {
4044*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4045*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
4046*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
4047*9880d681SAndroid Build Coastguard Worker if (!Tok.is(AsmToken::Identifier))
4048*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4049*9880d681SAndroid Build Coastguard Worker StringRef Mask = Tok.getString();
4050*9880d681SAndroid Build Coastguard Worker
4051*9880d681SAndroid Build Coastguard Worker if (isMClass()) {
4052*9880d681SAndroid Build Coastguard Worker // See ARMv6-M 10.1.1
4053*9880d681SAndroid Build Coastguard Worker std::string Name = Mask.lower();
4054*9880d681SAndroid Build Coastguard Worker unsigned FlagsVal = StringSwitch<unsigned>(Name)
4055*9880d681SAndroid Build Coastguard Worker // Note: in the documentation:
4056*9880d681SAndroid Build Coastguard Worker // ARM deprecates using MSR APSR without a _<bits> qualifier as an alias
4057*9880d681SAndroid Build Coastguard Worker // for MSR APSR_nzcvq.
4058*9880d681SAndroid Build Coastguard Worker // but we do make it an alias here. This is so to get the "mask encoding"
4059*9880d681SAndroid Build Coastguard Worker // bits correct on MSR APSR writes.
4060*9880d681SAndroid Build Coastguard Worker //
4061*9880d681SAndroid Build Coastguard Worker // FIXME: Note the 0xc00 "mask encoding" bits version of the registers
4062*9880d681SAndroid Build Coastguard Worker // should really only be allowed when writing a special register. Note
4063*9880d681SAndroid Build Coastguard Worker // they get dropped in the MRS instruction reading a special register as
4064*9880d681SAndroid Build Coastguard Worker // the SYSm field is only 8 bits.
4065*9880d681SAndroid Build Coastguard Worker .Case("apsr", 0x800)
4066*9880d681SAndroid Build Coastguard Worker .Case("apsr_nzcvq", 0x800)
4067*9880d681SAndroid Build Coastguard Worker .Case("apsr_g", 0x400)
4068*9880d681SAndroid Build Coastguard Worker .Case("apsr_nzcvqg", 0xc00)
4069*9880d681SAndroid Build Coastguard Worker .Case("iapsr", 0x801)
4070*9880d681SAndroid Build Coastguard Worker .Case("iapsr_nzcvq", 0x801)
4071*9880d681SAndroid Build Coastguard Worker .Case("iapsr_g", 0x401)
4072*9880d681SAndroid Build Coastguard Worker .Case("iapsr_nzcvqg", 0xc01)
4073*9880d681SAndroid Build Coastguard Worker .Case("eapsr", 0x802)
4074*9880d681SAndroid Build Coastguard Worker .Case("eapsr_nzcvq", 0x802)
4075*9880d681SAndroid Build Coastguard Worker .Case("eapsr_g", 0x402)
4076*9880d681SAndroid Build Coastguard Worker .Case("eapsr_nzcvqg", 0xc02)
4077*9880d681SAndroid Build Coastguard Worker .Case("xpsr", 0x803)
4078*9880d681SAndroid Build Coastguard Worker .Case("xpsr_nzcvq", 0x803)
4079*9880d681SAndroid Build Coastguard Worker .Case("xpsr_g", 0x403)
4080*9880d681SAndroid Build Coastguard Worker .Case("xpsr_nzcvqg", 0xc03)
4081*9880d681SAndroid Build Coastguard Worker .Case("ipsr", 0x805)
4082*9880d681SAndroid Build Coastguard Worker .Case("epsr", 0x806)
4083*9880d681SAndroid Build Coastguard Worker .Case("iepsr", 0x807)
4084*9880d681SAndroid Build Coastguard Worker .Case("msp", 0x808)
4085*9880d681SAndroid Build Coastguard Worker .Case("psp", 0x809)
4086*9880d681SAndroid Build Coastguard Worker .Case("primask", 0x810)
4087*9880d681SAndroid Build Coastguard Worker .Case("basepri", 0x811)
4088*9880d681SAndroid Build Coastguard Worker .Case("basepri_max", 0x812)
4089*9880d681SAndroid Build Coastguard Worker .Case("faultmask", 0x813)
4090*9880d681SAndroid Build Coastguard Worker .Case("control", 0x814)
4091*9880d681SAndroid Build Coastguard Worker .Case("msplim", 0x80a)
4092*9880d681SAndroid Build Coastguard Worker .Case("psplim", 0x80b)
4093*9880d681SAndroid Build Coastguard Worker .Case("msp_ns", 0x888)
4094*9880d681SAndroid Build Coastguard Worker .Case("psp_ns", 0x889)
4095*9880d681SAndroid Build Coastguard Worker .Case("msplim_ns", 0x88a)
4096*9880d681SAndroid Build Coastguard Worker .Case("psplim_ns", 0x88b)
4097*9880d681SAndroid Build Coastguard Worker .Case("primask_ns", 0x890)
4098*9880d681SAndroid Build Coastguard Worker .Case("basepri_ns", 0x891)
4099*9880d681SAndroid Build Coastguard Worker .Case("basepri_max_ns", 0x892)
4100*9880d681SAndroid Build Coastguard Worker .Case("faultmask_ns", 0x893)
4101*9880d681SAndroid Build Coastguard Worker .Case("control_ns", 0x894)
4102*9880d681SAndroid Build Coastguard Worker .Case("sp_ns", 0x898)
4103*9880d681SAndroid Build Coastguard Worker .Default(~0U);
4104*9880d681SAndroid Build Coastguard Worker
4105*9880d681SAndroid Build Coastguard Worker if (FlagsVal == ~0U)
4106*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4107*9880d681SAndroid Build Coastguard Worker
4108*9880d681SAndroid Build Coastguard Worker if (!hasDSP() && (FlagsVal & 0x400))
4109*9880d681SAndroid Build Coastguard Worker // The _g and _nzcvqg versions are only valid if the DSP extension is
4110*9880d681SAndroid Build Coastguard Worker // available.
4111*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4112*9880d681SAndroid Build Coastguard Worker
4113*9880d681SAndroid Build Coastguard Worker if (!hasV7Ops() && FlagsVal >= 0x811 && FlagsVal <= 0x813)
4114*9880d681SAndroid Build Coastguard Worker // basepri, basepri_max and faultmask only valid for V7m.
4115*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4116*9880d681SAndroid Build Coastguard Worker
4117*9880d681SAndroid Build Coastguard Worker if (!has8MSecExt() && (FlagsVal == 0x80a || FlagsVal == 0x80b ||
4118*9880d681SAndroid Build Coastguard Worker (FlagsVal > 0x814 && FlagsVal < 0xc00)))
4119*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4120*9880d681SAndroid Build Coastguard Worker
4121*9880d681SAndroid Build Coastguard Worker if (!hasV8MMainline() && (FlagsVal == 0x88a || FlagsVal == 0x88b ||
4122*9880d681SAndroid Build Coastguard Worker (FlagsVal > 0x890 && FlagsVal <= 0x893)))
4123*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4124*9880d681SAndroid Build Coastguard Worker
4125*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
4126*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
4127*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4128*9880d681SAndroid Build Coastguard Worker }
4129*9880d681SAndroid Build Coastguard Worker
4130*9880d681SAndroid Build Coastguard Worker // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
4131*9880d681SAndroid Build Coastguard Worker size_t Start = 0, Next = Mask.find('_');
4132*9880d681SAndroid Build Coastguard Worker StringRef Flags = "";
4133*9880d681SAndroid Build Coastguard Worker std::string SpecReg = Mask.slice(Start, Next).lower();
4134*9880d681SAndroid Build Coastguard Worker if (Next != StringRef::npos)
4135*9880d681SAndroid Build Coastguard Worker Flags = Mask.slice(Next+1, Mask.size());
4136*9880d681SAndroid Build Coastguard Worker
4137*9880d681SAndroid Build Coastguard Worker // FlagsVal contains the complete mask:
4138*9880d681SAndroid Build Coastguard Worker // 3-0: Mask
4139*9880d681SAndroid Build Coastguard Worker // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
4140*9880d681SAndroid Build Coastguard Worker unsigned FlagsVal = 0;
4141*9880d681SAndroid Build Coastguard Worker
4142*9880d681SAndroid Build Coastguard Worker if (SpecReg == "apsr") {
4143*9880d681SAndroid Build Coastguard Worker FlagsVal = StringSwitch<unsigned>(Flags)
4144*9880d681SAndroid Build Coastguard Worker .Case("nzcvq", 0x8) // same as CPSR_f
4145*9880d681SAndroid Build Coastguard Worker .Case("g", 0x4) // same as CPSR_s
4146*9880d681SAndroid Build Coastguard Worker .Case("nzcvqg", 0xc) // same as CPSR_fs
4147*9880d681SAndroid Build Coastguard Worker .Default(~0U);
4148*9880d681SAndroid Build Coastguard Worker
4149*9880d681SAndroid Build Coastguard Worker if (FlagsVal == ~0U) {
4150*9880d681SAndroid Build Coastguard Worker if (!Flags.empty())
4151*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4152*9880d681SAndroid Build Coastguard Worker else
4153*9880d681SAndroid Build Coastguard Worker FlagsVal = 8; // No flag
4154*9880d681SAndroid Build Coastguard Worker }
4155*9880d681SAndroid Build Coastguard Worker } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
4156*9880d681SAndroid Build Coastguard Worker // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
4157*9880d681SAndroid Build Coastguard Worker if (Flags == "all" || Flags == "")
4158*9880d681SAndroid Build Coastguard Worker Flags = "fc";
4159*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = Flags.size(); i != e; ++i) {
4160*9880d681SAndroid Build Coastguard Worker unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
4161*9880d681SAndroid Build Coastguard Worker .Case("c", 1)
4162*9880d681SAndroid Build Coastguard Worker .Case("x", 2)
4163*9880d681SAndroid Build Coastguard Worker .Case("s", 4)
4164*9880d681SAndroid Build Coastguard Worker .Case("f", 8)
4165*9880d681SAndroid Build Coastguard Worker .Default(~0U);
4166*9880d681SAndroid Build Coastguard Worker
4167*9880d681SAndroid Build Coastguard Worker // If some specific flag is already set, it means that some letter is
4168*9880d681SAndroid Build Coastguard Worker // present more than once, this is not acceptable.
4169*9880d681SAndroid Build Coastguard Worker if (FlagsVal == ~0U || (FlagsVal & Flag))
4170*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4171*9880d681SAndroid Build Coastguard Worker FlagsVal |= Flag;
4172*9880d681SAndroid Build Coastguard Worker }
4173*9880d681SAndroid Build Coastguard Worker } else // No match for special register.
4174*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4175*9880d681SAndroid Build Coastguard Worker
4176*9880d681SAndroid Build Coastguard Worker // Special register without flags is NOT equivalent to "fc" flags.
4177*9880d681SAndroid Build Coastguard Worker // NOTE: This is a divergence from gas' behavior. Uncommenting the following
4178*9880d681SAndroid Build Coastguard Worker // two lines would enable gas compatibility at the expense of breaking
4179*9880d681SAndroid Build Coastguard Worker // round-tripping.
4180*9880d681SAndroid Build Coastguard Worker //
4181*9880d681SAndroid Build Coastguard Worker // if (!FlagsVal)
4182*9880d681SAndroid Build Coastguard Worker // FlagsVal = 0x9;
4183*9880d681SAndroid Build Coastguard Worker
4184*9880d681SAndroid Build Coastguard Worker // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
4185*9880d681SAndroid Build Coastguard Worker if (SpecReg == "spsr")
4186*9880d681SAndroid Build Coastguard Worker FlagsVal |= 16;
4187*9880d681SAndroid Build Coastguard Worker
4188*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
4189*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
4190*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4191*9880d681SAndroid Build Coastguard Worker }
4192*9880d681SAndroid Build Coastguard Worker
4193*9880d681SAndroid Build Coastguard Worker /// parseBankedRegOperand - Try to parse a banked register (e.g. "lr_irq") for
4194*9880d681SAndroid Build Coastguard Worker /// use in the MRS/MSR instructions added to support virtualization.
4195*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseBankedRegOperand(OperandVector & Operands)4196*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) {
4197*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4198*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
4199*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
4200*9880d681SAndroid Build Coastguard Worker if (!Tok.is(AsmToken::Identifier))
4201*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4202*9880d681SAndroid Build Coastguard Worker StringRef RegName = Tok.getString();
4203*9880d681SAndroid Build Coastguard Worker
4204*9880d681SAndroid Build Coastguard Worker // The values here come from B9.2.3 of the ARM ARM, where bits 4-0 are SysM
4205*9880d681SAndroid Build Coastguard Worker // and bit 5 is R.
4206*9880d681SAndroid Build Coastguard Worker unsigned Encoding = StringSwitch<unsigned>(RegName.lower())
4207*9880d681SAndroid Build Coastguard Worker .Case("r8_usr", 0x00)
4208*9880d681SAndroid Build Coastguard Worker .Case("r9_usr", 0x01)
4209*9880d681SAndroid Build Coastguard Worker .Case("r10_usr", 0x02)
4210*9880d681SAndroid Build Coastguard Worker .Case("r11_usr", 0x03)
4211*9880d681SAndroid Build Coastguard Worker .Case("r12_usr", 0x04)
4212*9880d681SAndroid Build Coastguard Worker .Case("sp_usr", 0x05)
4213*9880d681SAndroid Build Coastguard Worker .Case("lr_usr", 0x06)
4214*9880d681SAndroid Build Coastguard Worker .Case("r8_fiq", 0x08)
4215*9880d681SAndroid Build Coastguard Worker .Case("r9_fiq", 0x09)
4216*9880d681SAndroid Build Coastguard Worker .Case("r10_fiq", 0x0a)
4217*9880d681SAndroid Build Coastguard Worker .Case("r11_fiq", 0x0b)
4218*9880d681SAndroid Build Coastguard Worker .Case("r12_fiq", 0x0c)
4219*9880d681SAndroid Build Coastguard Worker .Case("sp_fiq", 0x0d)
4220*9880d681SAndroid Build Coastguard Worker .Case("lr_fiq", 0x0e)
4221*9880d681SAndroid Build Coastguard Worker .Case("lr_irq", 0x10)
4222*9880d681SAndroid Build Coastguard Worker .Case("sp_irq", 0x11)
4223*9880d681SAndroid Build Coastguard Worker .Case("lr_svc", 0x12)
4224*9880d681SAndroid Build Coastguard Worker .Case("sp_svc", 0x13)
4225*9880d681SAndroid Build Coastguard Worker .Case("lr_abt", 0x14)
4226*9880d681SAndroid Build Coastguard Worker .Case("sp_abt", 0x15)
4227*9880d681SAndroid Build Coastguard Worker .Case("lr_und", 0x16)
4228*9880d681SAndroid Build Coastguard Worker .Case("sp_und", 0x17)
4229*9880d681SAndroid Build Coastguard Worker .Case("lr_mon", 0x1c)
4230*9880d681SAndroid Build Coastguard Worker .Case("sp_mon", 0x1d)
4231*9880d681SAndroid Build Coastguard Worker .Case("elr_hyp", 0x1e)
4232*9880d681SAndroid Build Coastguard Worker .Case("sp_hyp", 0x1f)
4233*9880d681SAndroid Build Coastguard Worker .Case("spsr_fiq", 0x2e)
4234*9880d681SAndroid Build Coastguard Worker .Case("spsr_irq", 0x30)
4235*9880d681SAndroid Build Coastguard Worker .Case("spsr_svc", 0x32)
4236*9880d681SAndroid Build Coastguard Worker .Case("spsr_abt", 0x34)
4237*9880d681SAndroid Build Coastguard Worker .Case("spsr_und", 0x36)
4238*9880d681SAndroid Build Coastguard Worker .Case("spsr_mon", 0x3c)
4239*9880d681SAndroid Build Coastguard Worker .Case("spsr_hyp", 0x3e)
4240*9880d681SAndroid Build Coastguard Worker .Default(~0U);
4241*9880d681SAndroid Build Coastguard Worker
4242*9880d681SAndroid Build Coastguard Worker if (Encoding == ~0U)
4243*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4244*9880d681SAndroid Build Coastguard Worker
4245*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat identifier token.
4246*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S));
4247*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4248*9880d681SAndroid Build Coastguard Worker }
4249*9880d681SAndroid Build Coastguard Worker
4250*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parsePKHImm(OperandVector & Operands,StringRef Op,int Low,int High)4251*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, int Low,
4252*9880d681SAndroid Build Coastguard Worker int High) {
4253*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4254*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
4255*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier)) {
4256*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), Op + " operand expected.");
4257*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4258*9880d681SAndroid Build Coastguard Worker }
4259*9880d681SAndroid Build Coastguard Worker StringRef ShiftName = Tok.getString();
4260*9880d681SAndroid Build Coastguard Worker std::string LowerOp = Op.lower();
4261*9880d681SAndroid Build Coastguard Worker std::string UpperOp = Op.upper();
4262*9880d681SAndroid Build Coastguard Worker if (ShiftName != LowerOp && ShiftName != UpperOp) {
4263*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), Op + " operand expected.");
4264*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4265*9880d681SAndroid Build Coastguard Worker }
4266*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat shift type token.
4267*9880d681SAndroid Build Coastguard Worker
4268*9880d681SAndroid Build Coastguard Worker // There must be a '#' and a shift amount.
4269*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Hash) &&
4270*9880d681SAndroid Build Coastguard Worker Parser.getTok().isNot(AsmToken::Dollar)) {
4271*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "'#' expected");
4272*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4273*9880d681SAndroid Build Coastguard Worker }
4274*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat hash token.
4275*9880d681SAndroid Build Coastguard Worker
4276*9880d681SAndroid Build Coastguard Worker const MCExpr *ShiftAmount;
4277*9880d681SAndroid Build Coastguard Worker SMLoc Loc = Parser.getTok().getLoc();
4278*9880d681SAndroid Build Coastguard Worker SMLoc EndLoc;
4279*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(ShiftAmount, EndLoc)) {
4280*9880d681SAndroid Build Coastguard Worker Error(Loc, "illegal expression");
4281*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4282*9880d681SAndroid Build Coastguard Worker }
4283*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
4284*9880d681SAndroid Build Coastguard Worker if (!CE) {
4285*9880d681SAndroid Build Coastguard Worker Error(Loc, "constant expression expected");
4286*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4287*9880d681SAndroid Build Coastguard Worker }
4288*9880d681SAndroid Build Coastguard Worker int Val = CE->getValue();
4289*9880d681SAndroid Build Coastguard Worker if (Val < Low || Val > High) {
4290*9880d681SAndroid Build Coastguard Worker Error(Loc, "immediate value out of range");
4291*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4292*9880d681SAndroid Build Coastguard Worker }
4293*9880d681SAndroid Build Coastguard Worker
4294*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc));
4295*9880d681SAndroid Build Coastguard Worker
4296*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4297*9880d681SAndroid Build Coastguard Worker }
4298*9880d681SAndroid Build Coastguard Worker
4299*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseSetEndImm(OperandVector & Operands)4300*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseSetEndImm(OperandVector &Operands) {
4301*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4302*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
4303*9880d681SAndroid Build Coastguard Worker SMLoc S = Tok.getLoc();
4304*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier)) {
4305*9880d681SAndroid Build Coastguard Worker Error(S, "'be' or 'le' operand expected");
4306*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4307*9880d681SAndroid Build Coastguard Worker }
4308*9880d681SAndroid Build Coastguard Worker int Val = StringSwitch<int>(Tok.getString().lower())
4309*9880d681SAndroid Build Coastguard Worker .Case("be", 1)
4310*9880d681SAndroid Build Coastguard Worker .Case("le", 0)
4311*9880d681SAndroid Build Coastguard Worker .Default(-1);
4312*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the token.
4313*9880d681SAndroid Build Coastguard Worker
4314*9880d681SAndroid Build Coastguard Worker if (Val == -1) {
4315*9880d681SAndroid Build Coastguard Worker Error(S, "'be' or 'le' operand expected");
4316*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4317*9880d681SAndroid Build Coastguard Worker }
4318*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::create(Val,
4319*9880d681SAndroid Build Coastguard Worker getContext()),
4320*9880d681SAndroid Build Coastguard Worker S, Tok.getEndLoc()));
4321*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4322*9880d681SAndroid Build Coastguard Worker }
4323*9880d681SAndroid Build Coastguard Worker
4324*9880d681SAndroid Build Coastguard Worker /// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
4325*9880d681SAndroid Build Coastguard Worker /// instructions. Legal values are:
4326*9880d681SAndroid Build Coastguard Worker /// lsl #n 'n' in [0,31]
4327*9880d681SAndroid Build Coastguard Worker /// asr #n 'n' in [1,32]
4328*9880d681SAndroid Build Coastguard Worker /// n == 32 encoded as n == 0.
4329*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseShifterImm(OperandVector & Operands)4330*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseShifterImm(OperandVector &Operands) {
4331*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4332*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
4333*9880d681SAndroid Build Coastguard Worker SMLoc S = Tok.getLoc();
4334*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier)) {
4335*9880d681SAndroid Build Coastguard Worker Error(S, "shift operator 'asr' or 'lsl' expected");
4336*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4337*9880d681SAndroid Build Coastguard Worker }
4338*9880d681SAndroid Build Coastguard Worker StringRef ShiftName = Tok.getString();
4339*9880d681SAndroid Build Coastguard Worker bool isASR;
4340*9880d681SAndroid Build Coastguard Worker if (ShiftName == "lsl" || ShiftName == "LSL")
4341*9880d681SAndroid Build Coastguard Worker isASR = false;
4342*9880d681SAndroid Build Coastguard Worker else if (ShiftName == "asr" || ShiftName == "ASR")
4343*9880d681SAndroid Build Coastguard Worker isASR = true;
4344*9880d681SAndroid Build Coastguard Worker else {
4345*9880d681SAndroid Build Coastguard Worker Error(S, "shift operator 'asr' or 'lsl' expected");
4346*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4347*9880d681SAndroid Build Coastguard Worker }
4348*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the operator.
4349*9880d681SAndroid Build Coastguard Worker
4350*9880d681SAndroid Build Coastguard Worker // A '#' and a shift amount.
4351*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Hash) &&
4352*9880d681SAndroid Build Coastguard Worker Parser.getTok().isNot(AsmToken::Dollar)) {
4353*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "'#' expected");
4354*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4355*9880d681SAndroid Build Coastguard Worker }
4356*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat hash token.
4357*9880d681SAndroid Build Coastguard Worker SMLoc ExLoc = Parser.getTok().getLoc();
4358*9880d681SAndroid Build Coastguard Worker
4359*9880d681SAndroid Build Coastguard Worker const MCExpr *ShiftAmount;
4360*9880d681SAndroid Build Coastguard Worker SMLoc EndLoc;
4361*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(ShiftAmount, EndLoc)) {
4362*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "malformed shift expression");
4363*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4364*9880d681SAndroid Build Coastguard Worker }
4365*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
4366*9880d681SAndroid Build Coastguard Worker if (!CE) {
4367*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "shift amount must be an immediate");
4368*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4369*9880d681SAndroid Build Coastguard Worker }
4370*9880d681SAndroid Build Coastguard Worker
4371*9880d681SAndroid Build Coastguard Worker int64_t Val = CE->getValue();
4372*9880d681SAndroid Build Coastguard Worker if (isASR) {
4373*9880d681SAndroid Build Coastguard Worker // Shift amount must be in [1,32]
4374*9880d681SAndroid Build Coastguard Worker if (Val < 1 || Val > 32) {
4375*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "'asr' shift amount must be in range [1,32]");
4376*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4377*9880d681SAndroid Build Coastguard Worker }
4378*9880d681SAndroid Build Coastguard Worker // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
4379*9880d681SAndroid Build Coastguard Worker if (isThumb() && Val == 32) {
4380*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "'asr #32' shift amount not allowed in Thumb mode");
4381*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4382*9880d681SAndroid Build Coastguard Worker }
4383*9880d681SAndroid Build Coastguard Worker if (Val == 32) Val = 0;
4384*9880d681SAndroid Build Coastguard Worker } else {
4385*9880d681SAndroid Build Coastguard Worker // Shift amount must be in [1,32]
4386*9880d681SAndroid Build Coastguard Worker if (Val < 0 || Val > 31) {
4387*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "'lsr' shift amount must be in range [0,31]");
4388*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4389*9880d681SAndroid Build Coastguard Worker }
4390*9880d681SAndroid Build Coastguard Worker }
4391*9880d681SAndroid Build Coastguard Worker
4392*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc));
4393*9880d681SAndroid Build Coastguard Worker
4394*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4395*9880d681SAndroid Build Coastguard Worker }
4396*9880d681SAndroid Build Coastguard Worker
4397*9880d681SAndroid Build Coastguard Worker /// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
4398*9880d681SAndroid Build Coastguard Worker /// of instructions. Legal values are:
4399*9880d681SAndroid Build Coastguard Worker /// ror #n 'n' in {0, 8, 16, 24}
4400*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseRotImm(OperandVector & Operands)4401*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseRotImm(OperandVector &Operands) {
4402*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4403*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
4404*9880d681SAndroid Build Coastguard Worker SMLoc S = Tok.getLoc();
4405*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier))
4406*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4407*9880d681SAndroid Build Coastguard Worker StringRef ShiftName = Tok.getString();
4408*9880d681SAndroid Build Coastguard Worker if (ShiftName != "ror" && ShiftName != "ROR")
4409*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4410*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the operator.
4411*9880d681SAndroid Build Coastguard Worker
4412*9880d681SAndroid Build Coastguard Worker // A '#' and a rotate amount.
4413*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Hash) &&
4414*9880d681SAndroid Build Coastguard Worker Parser.getTok().isNot(AsmToken::Dollar)) {
4415*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "'#' expected");
4416*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4417*9880d681SAndroid Build Coastguard Worker }
4418*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat hash token.
4419*9880d681SAndroid Build Coastguard Worker SMLoc ExLoc = Parser.getTok().getLoc();
4420*9880d681SAndroid Build Coastguard Worker
4421*9880d681SAndroid Build Coastguard Worker const MCExpr *ShiftAmount;
4422*9880d681SAndroid Build Coastguard Worker SMLoc EndLoc;
4423*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(ShiftAmount, EndLoc)) {
4424*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "malformed rotate expression");
4425*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4426*9880d681SAndroid Build Coastguard Worker }
4427*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
4428*9880d681SAndroid Build Coastguard Worker if (!CE) {
4429*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "rotate amount must be an immediate");
4430*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4431*9880d681SAndroid Build Coastguard Worker }
4432*9880d681SAndroid Build Coastguard Worker
4433*9880d681SAndroid Build Coastguard Worker int64_t Val = CE->getValue();
4434*9880d681SAndroid Build Coastguard Worker // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
4435*9880d681SAndroid Build Coastguard Worker // normally, zero is represented in asm by omitting the rotate operand
4436*9880d681SAndroid Build Coastguard Worker // entirely.
4437*9880d681SAndroid Build Coastguard Worker if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
4438*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "'ror' rotate amount must be 8, 16, or 24");
4439*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4440*9880d681SAndroid Build Coastguard Worker }
4441*9880d681SAndroid Build Coastguard Worker
4442*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc));
4443*9880d681SAndroid Build Coastguard Worker
4444*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4445*9880d681SAndroid Build Coastguard Worker }
4446*9880d681SAndroid Build Coastguard Worker
4447*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseModImm(OperandVector & Operands)4448*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseModImm(OperandVector &Operands) {
4449*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4450*9880d681SAndroid Build Coastguard Worker MCAsmLexer &Lexer = getLexer();
4451*9880d681SAndroid Build Coastguard Worker int64_t Imm1, Imm2;
4452*9880d681SAndroid Build Coastguard Worker
4453*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
4454*9880d681SAndroid Build Coastguard Worker
4455*9880d681SAndroid Build Coastguard Worker // 1) A mod_imm operand can appear in the place of a register name:
4456*9880d681SAndroid Build Coastguard Worker // add r0, #mod_imm
4457*9880d681SAndroid Build Coastguard Worker // add r0, r0, #mod_imm
4458*9880d681SAndroid Build Coastguard Worker // to correctly handle the latter, we bail out as soon as we see an
4459*9880d681SAndroid Build Coastguard Worker // identifier.
4460*9880d681SAndroid Build Coastguard Worker //
4461*9880d681SAndroid Build Coastguard Worker // 2) Similarly, we do not want to parse into complex operands:
4462*9880d681SAndroid Build Coastguard Worker // mov r0, #mod_imm
4463*9880d681SAndroid Build Coastguard Worker // mov r0, :lower16:(_foo)
4464*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Identifier) ||
4465*9880d681SAndroid Build Coastguard Worker Parser.getTok().is(AsmToken::Colon))
4466*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4467*9880d681SAndroid Build Coastguard Worker
4468*9880d681SAndroid Build Coastguard Worker // Hash (dollar) is optional as per the ARMARM
4469*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Hash) ||
4470*9880d681SAndroid Build Coastguard Worker Parser.getTok().is(AsmToken::Dollar)) {
4471*9880d681SAndroid Build Coastguard Worker // Avoid parsing into complex operands (#:)
4472*9880d681SAndroid Build Coastguard Worker if (Lexer.peekTok().is(AsmToken::Colon))
4473*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4474*9880d681SAndroid Build Coastguard Worker
4475*9880d681SAndroid Build Coastguard Worker // Eat the hash (dollar)
4476*9880d681SAndroid Build Coastguard Worker Parser.Lex();
4477*9880d681SAndroid Build Coastguard Worker }
4478*9880d681SAndroid Build Coastguard Worker
4479*9880d681SAndroid Build Coastguard Worker SMLoc Sx1, Ex1;
4480*9880d681SAndroid Build Coastguard Worker Sx1 = Parser.getTok().getLoc();
4481*9880d681SAndroid Build Coastguard Worker const MCExpr *Imm1Exp;
4482*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Imm1Exp, Ex1)) {
4483*9880d681SAndroid Build Coastguard Worker Error(Sx1, "malformed expression");
4484*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4485*9880d681SAndroid Build Coastguard Worker }
4486*9880d681SAndroid Build Coastguard Worker
4487*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm1Exp);
4488*9880d681SAndroid Build Coastguard Worker
4489*9880d681SAndroid Build Coastguard Worker if (CE) {
4490*9880d681SAndroid Build Coastguard Worker // Immediate must fit within 32-bits
4491*9880d681SAndroid Build Coastguard Worker Imm1 = CE->getValue();
4492*9880d681SAndroid Build Coastguard Worker int Enc = ARM_AM::getSOImmVal(Imm1);
4493*9880d681SAndroid Build Coastguard Worker if (Enc != -1 && Parser.getTok().is(AsmToken::EndOfStatement)) {
4494*9880d681SAndroid Build Coastguard Worker // We have a match!
4495*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateModImm((Enc & 0xFF),
4496*9880d681SAndroid Build Coastguard Worker (Enc & 0xF00) >> 7,
4497*9880d681SAndroid Build Coastguard Worker Sx1, Ex1));
4498*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4499*9880d681SAndroid Build Coastguard Worker }
4500*9880d681SAndroid Build Coastguard Worker
4501*9880d681SAndroid Build Coastguard Worker // We have parsed an immediate which is not for us, fallback to a plain
4502*9880d681SAndroid Build Coastguard Worker // immediate. This can happen for instruction aliases. For an example,
4503*9880d681SAndroid Build Coastguard Worker // ARMInstrInfo.td defines the alias [mov <-> mvn] which can transform
4504*9880d681SAndroid Build Coastguard Worker // a mov (mvn) with a mod_imm_neg/mod_imm_not operand into the opposite
4505*9880d681SAndroid Build Coastguard Worker // instruction with a mod_imm operand. The alias is defined such that the
4506*9880d681SAndroid Build Coastguard Worker // parser method is shared, that's why we have to do this here.
4507*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::EndOfStatement)) {
4508*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1));
4509*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4510*9880d681SAndroid Build Coastguard Worker }
4511*9880d681SAndroid Build Coastguard Worker } else {
4512*9880d681SAndroid Build Coastguard Worker // Operands like #(l1 - l2) can only be evaluated at a later stage (via an
4513*9880d681SAndroid Build Coastguard Worker // MCFixup). Fallback to a plain immediate.
4514*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1));
4515*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4516*9880d681SAndroid Build Coastguard Worker }
4517*9880d681SAndroid Build Coastguard Worker
4518*9880d681SAndroid Build Coastguard Worker // From this point onward, we expect the input to be a (#bits, #rot) pair
4519*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Comma)) {
4520*9880d681SAndroid Build Coastguard Worker Error(Sx1, "expected modified immediate operand: #[0, 255], #even[0-30]");
4521*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4522*9880d681SAndroid Build Coastguard Worker }
4523*9880d681SAndroid Build Coastguard Worker
4524*9880d681SAndroid Build Coastguard Worker if (Imm1 & ~0xFF) {
4525*9880d681SAndroid Build Coastguard Worker Error(Sx1, "immediate operand must a number in the range [0, 255]");
4526*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4527*9880d681SAndroid Build Coastguard Worker }
4528*9880d681SAndroid Build Coastguard Worker
4529*9880d681SAndroid Build Coastguard Worker // Eat the comma
4530*9880d681SAndroid Build Coastguard Worker Parser.Lex();
4531*9880d681SAndroid Build Coastguard Worker
4532*9880d681SAndroid Build Coastguard Worker // Repeat for #rot
4533*9880d681SAndroid Build Coastguard Worker SMLoc Sx2, Ex2;
4534*9880d681SAndroid Build Coastguard Worker Sx2 = Parser.getTok().getLoc();
4535*9880d681SAndroid Build Coastguard Worker
4536*9880d681SAndroid Build Coastguard Worker // Eat the optional hash (dollar)
4537*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Hash) ||
4538*9880d681SAndroid Build Coastguard Worker Parser.getTok().is(AsmToken::Dollar))
4539*9880d681SAndroid Build Coastguard Worker Parser.Lex();
4540*9880d681SAndroid Build Coastguard Worker
4541*9880d681SAndroid Build Coastguard Worker const MCExpr *Imm2Exp;
4542*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Imm2Exp, Ex2)) {
4543*9880d681SAndroid Build Coastguard Worker Error(Sx2, "malformed expression");
4544*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4545*9880d681SAndroid Build Coastguard Worker }
4546*9880d681SAndroid Build Coastguard Worker
4547*9880d681SAndroid Build Coastguard Worker CE = dyn_cast<MCConstantExpr>(Imm2Exp);
4548*9880d681SAndroid Build Coastguard Worker
4549*9880d681SAndroid Build Coastguard Worker if (CE) {
4550*9880d681SAndroid Build Coastguard Worker Imm2 = CE->getValue();
4551*9880d681SAndroid Build Coastguard Worker if (!(Imm2 & ~0x1E)) {
4552*9880d681SAndroid Build Coastguard Worker // We have a match!
4553*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2));
4554*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4555*9880d681SAndroid Build Coastguard Worker }
4556*9880d681SAndroid Build Coastguard Worker Error(Sx2, "immediate operand must an even number in the range [0, 30]");
4557*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4558*9880d681SAndroid Build Coastguard Worker } else {
4559*9880d681SAndroid Build Coastguard Worker Error(Sx2, "constant expression expected");
4560*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4561*9880d681SAndroid Build Coastguard Worker }
4562*9880d681SAndroid Build Coastguard Worker }
4563*9880d681SAndroid Build Coastguard Worker
4564*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseBitfield(OperandVector & Operands)4565*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseBitfield(OperandVector &Operands) {
4566*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4567*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
4568*9880d681SAndroid Build Coastguard Worker // The bitfield descriptor is really two operands, the LSB and the width.
4569*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Hash) &&
4570*9880d681SAndroid Build Coastguard Worker Parser.getTok().isNot(AsmToken::Dollar)) {
4571*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "'#' expected");
4572*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4573*9880d681SAndroid Build Coastguard Worker }
4574*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat hash token.
4575*9880d681SAndroid Build Coastguard Worker
4576*9880d681SAndroid Build Coastguard Worker const MCExpr *LSBExpr;
4577*9880d681SAndroid Build Coastguard Worker SMLoc E = Parser.getTok().getLoc();
4578*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(LSBExpr)) {
4579*9880d681SAndroid Build Coastguard Worker Error(E, "malformed immediate expression");
4580*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4581*9880d681SAndroid Build Coastguard Worker }
4582*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
4583*9880d681SAndroid Build Coastguard Worker if (!CE) {
4584*9880d681SAndroid Build Coastguard Worker Error(E, "'lsb' operand must be an immediate");
4585*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4586*9880d681SAndroid Build Coastguard Worker }
4587*9880d681SAndroid Build Coastguard Worker
4588*9880d681SAndroid Build Coastguard Worker int64_t LSB = CE->getValue();
4589*9880d681SAndroid Build Coastguard Worker // The LSB must be in the range [0,31]
4590*9880d681SAndroid Build Coastguard Worker if (LSB < 0 || LSB > 31) {
4591*9880d681SAndroid Build Coastguard Worker Error(E, "'lsb' operand must be in the range [0,31]");
4592*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4593*9880d681SAndroid Build Coastguard Worker }
4594*9880d681SAndroid Build Coastguard Worker E = Parser.getTok().getLoc();
4595*9880d681SAndroid Build Coastguard Worker
4596*9880d681SAndroid Build Coastguard Worker // Expect another immediate operand.
4597*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Comma)) {
4598*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "too few operands");
4599*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4600*9880d681SAndroid Build Coastguard Worker }
4601*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat hash token.
4602*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Hash) &&
4603*9880d681SAndroid Build Coastguard Worker Parser.getTok().isNot(AsmToken::Dollar)) {
4604*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "'#' expected");
4605*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4606*9880d681SAndroid Build Coastguard Worker }
4607*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat hash token.
4608*9880d681SAndroid Build Coastguard Worker
4609*9880d681SAndroid Build Coastguard Worker const MCExpr *WidthExpr;
4610*9880d681SAndroid Build Coastguard Worker SMLoc EndLoc;
4611*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(WidthExpr, EndLoc)) {
4612*9880d681SAndroid Build Coastguard Worker Error(E, "malformed immediate expression");
4613*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4614*9880d681SAndroid Build Coastguard Worker }
4615*9880d681SAndroid Build Coastguard Worker CE = dyn_cast<MCConstantExpr>(WidthExpr);
4616*9880d681SAndroid Build Coastguard Worker if (!CE) {
4617*9880d681SAndroid Build Coastguard Worker Error(E, "'width' operand must be an immediate");
4618*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4619*9880d681SAndroid Build Coastguard Worker }
4620*9880d681SAndroid Build Coastguard Worker
4621*9880d681SAndroid Build Coastguard Worker int64_t Width = CE->getValue();
4622*9880d681SAndroid Build Coastguard Worker // The LSB must be in the range [1,32-lsb]
4623*9880d681SAndroid Build Coastguard Worker if (Width < 1 || Width > 32 - LSB) {
4624*9880d681SAndroid Build Coastguard Worker Error(E, "'width' operand must be in the range [1,32-lsb]");
4625*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4626*9880d681SAndroid Build Coastguard Worker }
4627*9880d681SAndroid Build Coastguard Worker
4628*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc));
4629*9880d681SAndroid Build Coastguard Worker
4630*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4631*9880d681SAndroid Build Coastguard Worker }
4632*9880d681SAndroid Build Coastguard Worker
4633*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parsePostIdxReg(OperandVector & Operands)4634*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parsePostIdxReg(OperandVector &Operands) {
4635*9880d681SAndroid Build Coastguard Worker // Check for a post-index addressing register operand. Specifically:
4636*9880d681SAndroid Build Coastguard Worker // postidx_reg := '+' register {, shift}
4637*9880d681SAndroid Build Coastguard Worker // | '-' register {, shift}
4638*9880d681SAndroid Build Coastguard Worker // | register {, shift}
4639*9880d681SAndroid Build Coastguard Worker
4640*9880d681SAndroid Build Coastguard Worker // This method must return MatchOperand_NoMatch without consuming any tokens
4641*9880d681SAndroid Build Coastguard Worker // in the case where there is no match, as other alternatives take other
4642*9880d681SAndroid Build Coastguard Worker // parse methods.
4643*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4644*9880d681SAndroid Build Coastguard Worker AsmToken Tok = Parser.getTok();
4645*9880d681SAndroid Build Coastguard Worker SMLoc S = Tok.getLoc();
4646*9880d681SAndroid Build Coastguard Worker bool haveEaten = false;
4647*9880d681SAndroid Build Coastguard Worker bool isAdd = true;
4648*9880d681SAndroid Build Coastguard Worker if (Tok.is(AsmToken::Plus)) {
4649*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '+' token.
4650*9880d681SAndroid Build Coastguard Worker haveEaten = true;
4651*9880d681SAndroid Build Coastguard Worker } else if (Tok.is(AsmToken::Minus)) {
4652*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '-' token.
4653*9880d681SAndroid Build Coastguard Worker isAdd = false;
4654*9880d681SAndroid Build Coastguard Worker haveEaten = true;
4655*9880d681SAndroid Build Coastguard Worker }
4656*9880d681SAndroid Build Coastguard Worker
4657*9880d681SAndroid Build Coastguard Worker SMLoc E = Parser.getTok().getEndLoc();
4658*9880d681SAndroid Build Coastguard Worker int Reg = tryParseRegister();
4659*9880d681SAndroid Build Coastguard Worker if (Reg == -1) {
4660*9880d681SAndroid Build Coastguard Worker if (!haveEaten)
4661*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4662*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "register expected");
4663*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4664*9880d681SAndroid Build Coastguard Worker }
4665*9880d681SAndroid Build Coastguard Worker
4666*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
4667*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm = 0;
4668*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Comma)) {
4669*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the ','.
4670*9880d681SAndroid Build Coastguard Worker if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
4671*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4672*9880d681SAndroid Build Coastguard Worker
4673*9880d681SAndroid Build Coastguard Worker // FIXME: Only approximates end...may include intervening whitespace.
4674*9880d681SAndroid Build Coastguard Worker E = Parser.getTok().getLoc();
4675*9880d681SAndroid Build Coastguard Worker }
4676*9880d681SAndroid Build Coastguard Worker
4677*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
4678*9880d681SAndroid Build Coastguard Worker ShiftImm, S, E));
4679*9880d681SAndroid Build Coastguard Worker
4680*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4681*9880d681SAndroid Build Coastguard Worker }
4682*9880d681SAndroid Build Coastguard Worker
4683*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseAM3Offset(OperandVector & Operands)4684*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseAM3Offset(OperandVector &Operands) {
4685*9880d681SAndroid Build Coastguard Worker // Check for a post-index addressing register operand. Specifically:
4686*9880d681SAndroid Build Coastguard Worker // am3offset := '+' register
4687*9880d681SAndroid Build Coastguard Worker // | '-' register
4688*9880d681SAndroid Build Coastguard Worker // | register
4689*9880d681SAndroid Build Coastguard Worker // | # imm
4690*9880d681SAndroid Build Coastguard Worker // | # + imm
4691*9880d681SAndroid Build Coastguard Worker // | # - imm
4692*9880d681SAndroid Build Coastguard Worker
4693*9880d681SAndroid Build Coastguard Worker // This method must return MatchOperand_NoMatch without consuming any tokens
4694*9880d681SAndroid Build Coastguard Worker // in the case where there is no match, as other alternatives take other
4695*9880d681SAndroid Build Coastguard Worker // parse methods.
4696*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4697*9880d681SAndroid Build Coastguard Worker AsmToken Tok = Parser.getTok();
4698*9880d681SAndroid Build Coastguard Worker SMLoc S = Tok.getLoc();
4699*9880d681SAndroid Build Coastguard Worker
4700*9880d681SAndroid Build Coastguard Worker // Do immediates first, as we always parse those if we have a '#'.
4701*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Hash) ||
4702*9880d681SAndroid Build Coastguard Worker Parser.getTok().is(AsmToken::Dollar)) {
4703*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '#' or '$'.
4704*9880d681SAndroid Build Coastguard Worker // Explicitly look for a '-', as we need to encode negative zero
4705*9880d681SAndroid Build Coastguard Worker // differently.
4706*9880d681SAndroid Build Coastguard Worker bool isNegative = Parser.getTok().is(AsmToken::Minus);
4707*9880d681SAndroid Build Coastguard Worker const MCExpr *Offset;
4708*9880d681SAndroid Build Coastguard Worker SMLoc E;
4709*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Offset, E))
4710*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4711*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4712*9880d681SAndroid Build Coastguard Worker if (!CE) {
4713*9880d681SAndroid Build Coastguard Worker Error(S, "constant expression expected");
4714*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4715*9880d681SAndroid Build Coastguard Worker }
4716*9880d681SAndroid Build Coastguard Worker // Negative zero is encoded as the flag value INT32_MIN.
4717*9880d681SAndroid Build Coastguard Worker int32_t Val = CE->getValue();
4718*9880d681SAndroid Build Coastguard Worker if (isNegative && Val == 0)
4719*9880d681SAndroid Build Coastguard Worker Val = INT32_MIN;
4720*9880d681SAndroid Build Coastguard Worker
4721*9880d681SAndroid Build Coastguard Worker Operands.push_back(
4722*9880d681SAndroid Build Coastguard Worker ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, E));
4723*9880d681SAndroid Build Coastguard Worker
4724*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4725*9880d681SAndroid Build Coastguard Worker }
4726*9880d681SAndroid Build Coastguard Worker
4727*9880d681SAndroid Build Coastguard Worker
4728*9880d681SAndroid Build Coastguard Worker bool haveEaten = false;
4729*9880d681SAndroid Build Coastguard Worker bool isAdd = true;
4730*9880d681SAndroid Build Coastguard Worker if (Tok.is(AsmToken::Plus)) {
4731*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '+' token.
4732*9880d681SAndroid Build Coastguard Worker haveEaten = true;
4733*9880d681SAndroid Build Coastguard Worker } else if (Tok.is(AsmToken::Minus)) {
4734*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '-' token.
4735*9880d681SAndroid Build Coastguard Worker isAdd = false;
4736*9880d681SAndroid Build Coastguard Worker haveEaten = true;
4737*9880d681SAndroid Build Coastguard Worker }
4738*9880d681SAndroid Build Coastguard Worker
4739*9880d681SAndroid Build Coastguard Worker Tok = Parser.getTok();
4740*9880d681SAndroid Build Coastguard Worker int Reg = tryParseRegister();
4741*9880d681SAndroid Build Coastguard Worker if (Reg == -1) {
4742*9880d681SAndroid Build Coastguard Worker if (!haveEaten)
4743*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
4744*9880d681SAndroid Build Coastguard Worker Error(Tok.getLoc(), "register expected");
4745*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
4746*9880d681SAndroid Build Coastguard Worker }
4747*9880d681SAndroid Build Coastguard Worker
4748*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
4749*9880d681SAndroid Build Coastguard Worker 0, S, Tok.getEndLoc()));
4750*9880d681SAndroid Build Coastguard Worker
4751*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
4752*9880d681SAndroid Build Coastguard Worker }
4753*9880d681SAndroid Build Coastguard Worker
4754*9880d681SAndroid Build Coastguard Worker /// Convert parsed operands to MCInst. Needed here because this instruction
4755*9880d681SAndroid Build Coastguard Worker /// only has two register operands, but multiplication is commutative so
4756*9880d681SAndroid Build Coastguard Worker /// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN".
cvtThumbMultiply(MCInst & Inst,const OperandVector & Operands)4757*9880d681SAndroid Build Coastguard Worker void ARMAsmParser::cvtThumbMultiply(MCInst &Inst,
4758*9880d681SAndroid Build Coastguard Worker const OperandVector &Operands) {
4759*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1);
4760*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[1]).addCCOutOperands(Inst, 1);
4761*9880d681SAndroid Build Coastguard Worker // If we have a three-operand form, make sure to set Rn to be the operand
4762*9880d681SAndroid Build Coastguard Worker // that isn't the same as Rd.
4763*9880d681SAndroid Build Coastguard Worker unsigned RegOp = 4;
4764*9880d681SAndroid Build Coastguard Worker if (Operands.size() == 6 &&
4765*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[4]).getReg() ==
4766*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[3]).getReg())
4767*9880d681SAndroid Build Coastguard Worker RegOp = 5;
4768*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[RegOp]).addRegOperands(Inst, 1);
4769*9880d681SAndroid Build Coastguard Worker Inst.addOperand(Inst.getOperand(0));
4770*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[2]).addCondCodeOperands(Inst, 2);
4771*9880d681SAndroid Build Coastguard Worker }
4772*9880d681SAndroid Build Coastguard Worker
cvtThumbBranches(MCInst & Inst,const OperandVector & Operands)4773*9880d681SAndroid Build Coastguard Worker void ARMAsmParser::cvtThumbBranches(MCInst &Inst,
4774*9880d681SAndroid Build Coastguard Worker const OperandVector &Operands) {
4775*9880d681SAndroid Build Coastguard Worker int CondOp = -1, ImmOp = -1;
4776*9880d681SAndroid Build Coastguard Worker switch(Inst.getOpcode()) {
4777*9880d681SAndroid Build Coastguard Worker case ARM::tB:
4778*9880d681SAndroid Build Coastguard Worker case ARM::tBcc: CondOp = 1; ImmOp = 2; break;
4779*9880d681SAndroid Build Coastguard Worker
4780*9880d681SAndroid Build Coastguard Worker case ARM::t2B:
4781*9880d681SAndroid Build Coastguard Worker case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break;
4782*9880d681SAndroid Build Coastguard Worker
4783*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unexpected instruction in cvtThumbBranches");
4784*9880d681SAndroid Build Coastguard Worker }
4785*9880d681SAndroid Build Coastguard Worker // first decide whether or not the branch should be conditional
4786*9880d681SAndroid Build Coastguard Worker // by looking at it's location relative to an IT block
4787*9880d681SAndroid Build Coastguard Worker if(inITBlock()) {
4788*9880d681SAndroid Build Coastguard Worker // inside an IT block we cannot have any conditional branches. any
4789*9880d681SAndroid Build Coastguard Worker // such instructions needs to be converted to unconditional form
4790*9880d681SAndroid Build Coastguard Worker switch(Inst.getOpcode()) {
4791*9880d681SAndroid Build Coastguard Worker case ARM::tBcc: Inst.setOpcode(ARM::tB); break;
4792*9880d681SAndroid Build Coastguard Worker case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break;
4793*9880d681SAndroid Build Coastguard Worker }
4794*9880d681SAndroid Build Coastguard Worker } else {
4795*9880d681SAndroid Build Coastguard Worker // outside IT blocks we can only have unconditional branches with AL
4796*9880d681SAndroid Build Coastguard Worker // condition code or conditional branches with non-AL condition code
4797*9880d681SAndroid Build Coastguard Worker unsigned Cond = static_cast<ARMOperand &>(*Operands[CondOp]).getCondCode();
4798*9880d681SAndroid Build Coastguard Worker switch(Inst.getOpcode()) {
4799*9880d681SAndroid Build Coastguard Worker case ARM::tB:
4800*9880d681SAndroid Build Coastguard Worker case ARM::tBcc:
4801*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(Cond == ARMCC::AL ? ARM::tB : ARM::tBcc);
4802*9880d681SAndroid Build Coastguard Worker break;
4803*9880d681SAndroid Build Coastguard Worker case ARM::t2B:
4804*9880d681SAndroid Build Coastguard Worker case ARM::t2Bcc:
4805*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(Cond == ARMCC::AL ? ARM::t2B : ARM::t2Bcc);
4806*9880d681SAndroid Build Coastguard Worker break;
4807*9880d681SAndroid Build Coastguard Worker }
4808*9880d681SAndroid Build Coastguard Worker }
4809*9880d681SAndroid Build Coastguard Worker
4810*9880d681SAndroid Build Coastguard Worker // now decide on encoding size based on branch target range
4811*9880d681SAndroid Build Coastguard Worker switch(Inst.getOpcode()) {
4812*9880d681SAndroid Build Coastguard Worker // classify tB as either t2B or t1B based on range of immediate operand
4813*9880d681SAndroid Build Coastguard Worker case ARM::tB: {
4814*9880d681SAndroid Build Coastguard Worker ARMOperand &op = static_cast<ARMOperand &>(*Operands[ImmOp]);
4815*9880d681SAndroid Build Coastguard Worker if (!op.isSignedOffset<11, 1>() && isThumb() && hasV8MBaseline())
4816*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2B);
4817*9880d681SAndroid Build Coastguard Worker break;
4818*9880d681SAndroid Build Coastguard Worker }
4819*9880d681SAndroid Build Coastguard Worker // classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand
4820*9880d681SAndroid Build Coastguard Worker case ARM::tBcc: {
4821*9880d681SAndroid Build Coastguard Worker ARMOperand &op = static_cast<ARMOperand &>(*Operands[ImmOp]);
4822*9880d681SAndroid Build Coastguard Worker if (!op.isSignedOffset<8, 1>() && isThumb() && hasV8MBaseline())
4823*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2Bcc);
4824*9880d681SAndroid Build Coastguard Worker break;
4825*9880d681SAndroid Build Coastguard Worker }
4826*9880d681SAndroid Build Coastguard Worker }
4827*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[ImmOp]).addImmOperands(Inst, 1);
4828*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[CondOp]).addCondCodeOperands(Inst, 2);
4829*9880d681SAndroid Build Coastguard Worker }
4830*9880d681SAndroid Build Coastguard Worker
4831*9880d681SAndroid Build Coastguard Worker /// Parse an ARM memory expression, return false if successful else return true
4832*9880d681SAndroid Build Coastguard Worker /// or an error. The first token must be a '[' when called.
parseMemory(OperandVector & Operands)4833*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseMemory(OperandVector &Operands) {
4834*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
4835*9880d681SAndroid Build Coastguard Worker SMLoc S, E;
4836*9880d681SAndroid Build Coastguard Worker assert(Parser.getTok().is(AsmToken::LBrac) &&
4837*9880d681SAndroid Build Coastguard Worker "Token is not a Left Bracket");
4838*9880d681SAndroid Build Coastguard Worker S = Parser.getTok().getLoc();
4839*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat left bracket token.
4840*9880d681SAndroid Build Coastguard Worker
4841*9880d681SAndroid Build Coastguard Worker const AsmToken &BaseRegTok = Parser.getTok();
4842*9880d681SAndroid Build Coastguard Worker int BaseRegNum = tryParseRegister();
4843*9880d681SAndroid Build Coastguard Worker if (BaseRegNum == -1)
4844*9880d681SAndroid Build Coastguard Worker return Error(BaseRegTok.getLoc(), "register expected");
4845*9880d681SAndroid Build Coastguard Worker
4846*9880d681SAndroid Build Coastguard Worker // The next token must either be a comma, a colon or a closing bracket.
4847*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
4848*9880d681SAndroid Build Coastguard Worker if (!Tok.is(AsmToken::Colon) && !Tok.is(AsmToken::Comma) &&
4849*9880d681SAndroid Build Coastguard Worker !Tok.is(AsmToken::RBrac))
4850*9880d681SAndroid Build Coastguard Worker return Error(Tok.getLoc(), "malformed memory operand");
4851*9880d681SAndroid Build Coastguard Worker
4852*9880d681SAndroid Build Coastguard Worker if (Tok.is(AsmToken::RBrac)) {
4853*9880d681SAndroid Build Coastguard Worker E = Tok.getEndLoc();
4854*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat right bracket token.
4855*9880d681SAndroid Build Coastguard Worker
4856*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0,
4857*9880d681SAndroid Build Coastguard Worker ARM_AM::no_shift, 0, 0, false,
4858*9880d681SAndroid Build Coastguard Worker S, E));
4859*9880d681SAndroid Build Coastguard Worker
4860*9880d681SAndroid Build Coastguard Worker // If there's a pre-indexing writeback marker, '!', just add it as a token
4861*9880d681SAndroid Build Coastguard Worker // operand. It's rather odd, but syntactically valid.
4862*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Exclaim)) {
4863*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4864*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '!'.
4865*9880d681SAndroid Build Coastguard Worker }
4866*9880d681SAndroid Build Coastguard Worker
4867*9880d681SAndroid Build Coastguard Worker return false;
4868*9880d681SAndroid Build Coastguard Worker }
4869*9880d681SAndroid Build Coastguard Worker
4870*9880d681SAndroid Build Coastguard Worker assert((Tok.is(AsmToken::Colon) || Tok.is(AsmToken::Comma)) &&
4871*9880d681SAndroid Build Coastguard Worker "Lost colon or comma in memory operand?!");
4872*9880d681SAndroid Build Coastguard Worker if (Tok.is(AsmToken::Comma)) {
4873*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the comma.
4874*9880d681SAndroid Build Coastguard Worker }
4875*9880d681SAndroid Build Coastguard Worker
4876*9880d681SAndroid Build Coastguard Worker // If we have a ':', it's an alignment specifier.
4877*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Colon)) {
4878*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the ':'.
4879*9880d681SAndroid Build Coastguard Worker E = Parser.getTok().getLoc();
4880*9880d681SAndroid Build Coastguard Worker SMLoc AlignmentLoc = Tok.getLoc();
4881*9880d681SAndroid Build Coastguard Worker
4882*9880d681SAndroid Build Coastguard Worker const MCExpr *Expr;
4883*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Expr))
4884*9880d681SAndroid Build Coastguard Worker return true;
4885*9880d681SAndroid Build Coastguard Worker
4886*9880d681SAndroid Build Coastguard Worker // The expression has to be a constant. Memory references with relocations
4887*9880d681SAndroid Build Coastguard Worker // don't come through here, as they use the <label> forms of the relevant
4888*9880d681SAndroid Build Coastguard Worker // instructions.
4889*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4890*9880d681SAndroid Build Coastguard Worker if (!CE)
4891*9880d681SAndroid Build Coastguard Worker return Error (E, "constant expression expected");
4892*9880d681SAndroid Build Coastguard Worker
4893*9880d681SAndroid Build Coastguard Worker unsigned Align = 0;
4894*9880d681SAndroid Build Coastguard Worker switch (CE->getValue()) {
4895*9880d681SAndroid Build Coastguard Worker default:
4896*9880d681SAndroid Build Coastguard Worker return Error(E,
4897*9880d681SAndroid Build Coastguard Worker "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4898*9880d681SAndroid Build Coastguard Worker case 16: Align = 2; break;
4899*9880d681SAndroid Build Coastguard Worker case 32: Align = 4; break;
4900*9880d681SAndroid Build Coastguard Worker case 64: Align = 8; break;
4901*9880d681SAndroid Build Coastguard Worker case 128: Align = 16; break;
4902*9880d681SAndroid Build Coastguard Worker case 256: Align = 32; break;
4903*9880d681SAndroid Build Coastguard Worker }
4904*9880d681SAndroid Build Coastguard Worker
4905*9880d681SAndroid Build Coastguard Worker // Now we should have the closing ']'
4906*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::RBrac))
4907*9880d681SAndroid Build Coastguard Worker return Error(Parser.getTok().getLoc(), "']' expected");
4908*9880d681SAndroid Build Coastguard Worker E = Parser.getTok().getEndLoc();
4909*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat right bracket token.
4910*9880d681SAndroid Build Coastguard Worker
4911*9880d681SAndroid Build Coastguard Worker // Don't worry about range checking the value here. That's handled by
4912*9880d681SAndroid Build Coastguard Worker // the is*() predicates.
4913*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0,
4914*9880d681SAndroid Build Coastguard Worker ARM_AM::no_shift, 0, Align,
4915*9880d681SAndroid Build Coastguard Worker false, S, E, AlignmentLoc));
4916*9880d681SAndroid Build Coastguard Worker
4917*9880d681SAndroid Build Coastguard Worker // If there's a pre-indexing writeback marker, '!', just add it as a token
4918*9880d681SAndroid Build Coastguard Worker // operand.
4919*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Exclaim)) {
4920*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4921*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '!'.
4922*9880d681SAndroid Build Coastguard Worker }
4923*9880d681SAndroid Build Coastguard Worker
4924*9880d681SAndroid Build Coastguard Worker return false;
4925*9880d681SAndroid Build Coastguard Worker }
4926*9880d681SAndroid Build Coastguard Worker
4927*9880d681SAndroid Build Coastguard Worker // If we have a '#', it's an immediate offset, else assume it's a register
4928*9880d681SAndroid Build Coastguard Worker // offset. Be friendly and also accept a plain integer (without a leading
4929*9880d681SAndroid Build Coastguard Worker // hash) for gas compatibility.
4930*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Hash) ||
4931*9880d681SAndroid Build Coastguard Worker Parser.getTok().is(AsmToken::Dollar) ||
4932*9880d681SAndroid Build Coastguard Worker Parser.getTok().is(AsmToken::Integer)) {
4933*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Integer))
4934*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '#' or '$'.
4935*9880d681SAndroid Build Coastguard Worker E = Parser.getTok().getLoc();
4936*9880d681SAndroid Build Coastguard Worker
4937*9880d681SAndroid Build Coastguard Worker bool isNegative = getParser().getTok().is(AsmToken::Minus);
4938*9880d681SAndroid Build Coastguard Worker const MCExpr *Offset;
4939*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Offset))
4940*9880d681SAndroid Build Coastguard Worker return true;
4941*9880d681SAndroid Build Coastguard Worker
4942*9880d681SAndroid Build Coastguard Worker // The expression has to be a constant. Memory references with relocations
4943*9880d681SAndroid Build Coastguard Worker // don't come through here, as they use the <label> forms of the relevant
4944*9880d681SAndroid Build Coastguard Worker // instructions.
4945*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4946*9880d681SAndroid Build Coastguard Worker if (!CE)
4947*9880d681SAndroid Build Coastguard Worker return Error (E, "constant expression expected");
4948*9880d681SAndroid Build Coastguard Worker
4949*9880d681SAndroid Build Coastguard Worker // If the constant was #-0, represent it as INT32_MIN.
4950*9880d681SAndroid Build Coastguard Worker int32_t Val = CE->getValue();
4951*9880d681SAndroid Build Coastguard Worker if (isNegative && Val == 0)
4952*9880d681SAndroid Build Coastguard Worker CE = MCConstantExpr::create(INT32_MIN, getContext());
4953*9880d681SAndroid Build Coastguard Worker
4954*9880d681SAndroid Build Coastguard Worker // Now we should have the closing ']'
4955*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::RBrac))
4956*9880d681SAndroid Build Coastguard Worker return Error(Parser.getTok().getLoc(), "']' expected");
4957*9880d681SAndroid Build Coastguard Worker E = Parser.getTok().getEndLoc();
4958*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat right bracket token.
4959*9880d681SAndroid Build Coastguard Worker
4960*9880d681SAndroid Build Coastguard Worker // Don't worry about range checking the value here. That's handled by
4961*9880d681SAndroid Build Coastguard Worker // the is*() predicates.
4962*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
4963*9880d681SAndroid Build Coastguard Worker ARM_AM::no_shift, 0, 0,
4964*9880d681SAndroid Build Coastguard Worker false, S, E));
4965*9880d681SAndroid Build Coastguard Worker
4966*9880d681SAndroid Build Coastguard Worker // If there's a pre-indexing writeback marker, '!', just add it as a token
4967*9880d681SAndroid Build Coastguard Worker // operand.
4968*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Exclaim)) {
4969*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4970*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '!'.
4971*9880d681SAndroid Build Coastguard Worker }
4972*9880d681SAndroid Build Coastguard Worker
4973*9880d681SAndroid Build Coastguard Worker return false;
4974*9880d681SAndroid Build Coastguard Worker }
4975*9880d681SAndroid Build Coastguard Worker
4976*9880d681SAndroid Build Coastguard Worker // The register offset is optionally preceded by a '+' or '-'
4977*9880d681SAndroid Build Coastguard Worker bool isNegative = false;
4978*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Minus)) {
4979*9880d681SAndroid Build Coastguard Worker isNegative = true;
4980*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '-'.
4981*9880d681SAndroid Build Coastguard Worker } else if (Parser.getTok().is(AsmToken::Plus)) {
4982*9880d681SAndroid Build Coastguard Worker // Nothing to do.
4983*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '+'.
4984*9880d681SAndroid Build Coastguard Worker }
4985*9880d681SAndroid Build Coastguard Worker
4986*9880d681SAndroid Build Coastguard Worker E = Parser.getTok().getLoc();
4987*9880d681SAndroid Build Coastguard Worker int OffsetRegNum = tryParseRegister();
4988*9880d681SAndroid Build Coastguard Worker if (OffsetRegNum == -1)
4989*9880d681SAndroid Build Coastguard Worker return Error(E, "register expected");
4990*9880d681SAndroid Build Coastguard Worker
4991*9880d681SAndroid Build Coastguard Worker // If there's a shift operator, handle it.
4992*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
4993*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm = 0;
4994*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Comma)) {
4995*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the ','.
4996*9880d681SAndroid Build Coastguard Worker if (parseMemRegOffsetShift(ShiftType, ShiftImm))
4997*9880d681SAndroid Build Coastguard Worker return true;
4998*9880d681SAndroid Build Coastguard Worker }
4999*9880d681SAndroid Build Coastguard Worker
5000*9880d681SAndroid Build Coastguard Worker // Now we should have the closing ']'
5001*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::RBrac))
5002*9880d681SAndroid Build Coastguard Worker return Error(Parser.getTok().getLoc(), "']' expected");
5003*9880d681SAndroid Build Coastguard Worker E = Parser.getTok().getEndLoc();
5004*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat right bracket token.
5005*9880d681SAndroid Build Coastguard Worker
5006*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, OffsetRegNum,
5007*9880d681SAndroid Build Coastguard Worker ShiftType, ShiftImm, 0, isNegative,
5008*9880d681SAndroid Build Coastguard Worker S, E));
5009*9880d681SAndroid Build Coastguard Worker
5010*9880d681SAndroid Build Coastguard Worker // If there's a pre-indexing writeback marker, '!', just add it as a token
5011*9880d681SAndroid Build Coastguard Worker // operand.
5012*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Exclaim)) {
5013*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
5014*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '!'.
5015*9880d681SAndroid Build Coastguard Worker }
5016*9880d681SAndroid Build Coastguard Worker
5017*9880d681SAndroid Build Coastguard Worker return false;
5018*9880d681SAndroid Build Coastguard Worker }
5019*9880d681SAndroid Build Coastguard Worker
5020*9880d681SAndroid Build Coastguard Worker /// parseMemRegOffsetShift - one of these two:
5021*9880d681SAndroid Build Coastguard Worker /// ( lsl | lsr | asr | ror ) , # shift_amount
5022*9880d681SAndroid Build Coastguard Worker /// rrx
5023*9880d681SAndroid Build Coastguard Worker /// return true if it parses a shift otherwise it returns false.
parseMemRegOffsetShift(ARM_AM::ShiftOpc & St,unsigned & Amount)5024*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
5025*9880d681SAndroid Build Coastguard Worker unsigned &Amount) {
5026*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
5027*9880d681SAndroid Build Coastguard Worker SMLoc Loc = Parser.getTok().getLoc();
5028*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
5029*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier))
5030*9880d681SAndroid Build Coastguard Worker return true;
5031*9880d681SAndroid Build Coastguard Worker StringRef ShiftName = Tok.getString();
5032*9880d681SAndroid Build Coastguard Worker if (ShiftName == "lsl" || ShiftName == "LSL" ||
5033*9880d681SAndroid Build Coastguard Worker ShiftName == "asl" || ShiftName == "ASL")
5034*9880d681SAndroid Build Coastguard Worker St = ARM_AM::lsl;
5035*9880d681SAndroid Build Coastguard Worker else if (ShiftName == "lsr" || ShiftName == "LSR")
5036*9880d681SAndroid Build Coastguard Worker St = ARM_AM::lsr;
5037*9880d681SAndroid Build Coastguard Worker else if (ShiftName == "asr" || ShiftName == "ASR")
5038*9880d681SAndroid Build Coastguard Worker St = ARM_AM::asr;
5039*9880d681SAndroid Build Coastguard Worker else if (ShiftName == "ror" || ShiftName == "ROR")
5040*9880d681SAndroid Build Coastguard Worker St = ARM_AM::ror;
5041*9880d681SAndroid Build Coastguard Worker else if (ShiftName == "rrx" || ShiftName == "RRX")
5042*9880d681SAndroid Build Coastguard Worker St = ARM_AM::rrx;
5043*9880d681SAndroid Build Coastguard Worker else
5044*9880d681SAndroid Build Coastguard Worker return Error(Loc, "illegal shift operator");
5045*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat shift type token.
5046*9880d681SAndroid Build Coastguard Worker
5047*9880d681SAndroid Build Coastguard Worker // rrx stands alone.
5048*9880d681SAndroid Build Coastguard Worker Amount = 0;
5049*9880d681SAndroid Build Coastguard Worker if (St != ARM_AM::rrx) {
5050*9880d681SAndroid Build Coastguard Worker Loc = Parser.getTok().getLoc();
5051*9880d681SAndroid Build Coastguard Worker // A '#' and a shift amount.
5052*9880d681SAndroid Build Coastguard Worker const AsmToken &HashTok = Parser.getTok();
5053*9880d681SAndroid Build Coastguard Worker if (HashTok.isNot(AsmToken::Hash) &&
5054*9880d681SAndroid Build Coastguard Worker HashTok.isNot(AsmToken::Dollar))
5055*9880d681SAndroid Build Coastguard Worker return Error(HashTok.getLoc(), "'#' expected");
5056*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat hash token.
5057*9880d681SAndroid Build Coastguard Worker
5058*9880d681SAndroid Build Coastguard Worker const MCExpr *Expr;
5059*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Expr))
5060*9880d681SAndroid Build Coastguard Worker return true;
5061*9880d681SAndroid Build Coastguard Worker // Range check the immediate.
5062*9880d681SAndroid Build Coastguard Worker // lsl, ror: 0 <= imm <= 31
5063*9880d681SAndroid Build Coastguard Worker // lsr, asr: 0 <= imm <= 32
5064*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
5065*9880d681SAndroid Build Coastguard Worker if (!CE)
5066*9880d681SAndroid Build Coastguard Worker return Error(Loc, "shift amount must be an immediate");
5067*9880d681SAndroid Build Coastguard Worker int64_t Imm = CE->getValue();
5068*9880d681SAndroid Build Coastguard Worker if (Imm < 0 ||
5069*9880d681SAndroid Build Coastguard Worker ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
5070*9880d681SAndroid Build Coastguard Worker ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
5071*9880d681SAndroid Build Coastguard Worker return Error(Loc, "immediate shift value out of range");
5072*9880d681SAndroid Build Coastguard Worker // If <ShiftTy> #0, turn it into a no_shift.
5073*9880d681SAndroid Build Coastguard Worker if (Imm == 0)
5074*9880d681SAndroid Build Coastguard Worker St = ARM_AM::lsl;
5075*9880d681SAndroid Build Coastguard Worker // For consistency, treat lsr #32 and asr #32 as having immediate value 0.
5076*9880d681SAndroid Build Coastguard Worker if (Imm == 32)
5077*9880d681SAndroid Build Coastguard Worker Imm = 0;
5078*9880d681SAndroid Build Coastguard Worker Amount = Imm;
5079*9880d681SAndroid Build Coastguard Worker }
5080*9880d681SAndroid Build Coastguard Worker
5081*9880d681SAndroid Build Coastguard Worker return false;
5082*9880d681SAndroid Build Coastguard Worker }
5083*9880d681SAndroid Build Coastguard Worker
5084*9880d681SAndroid Build Coastguard Worker /// parseFPImm - A floating point immediate expression operand.
5085*9880d681SAndroid Build Coastguard Worker ARMAsmParser::OperandMatchResultTy
parseFPImm(OperandVector & Operands)5086*9880d681SAndroid Build Coastguard Worker ARMAsmParser::parseFPImm(OperandVector &Operands) {
5087*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
5088*9880d681SAndroid Build Coastguard Worker // Anything that can accept a floating point constant as an operand
5089*9880d681SAndroid Build Coastguard Worker // needs to go through here, as the regular parseExpression is
5090*9880d681SAndroid Build Coastguard Worker // integer only.
5091*9880d681SAndroid Build Coastguard Worker //
5092*9880d681SAndroid Build Coastguard Worker // This routine still creates a generic Immediate operand, containing
5093*9880d681SAndroid Build Coastguard Worker // a bitcast of the 64-bit floating point value. The various operands
5094*9880d681SAndroid Build Coastguard Worker // that accept floats can check whether the value is valid for them
5095*9880d681SAndroid Build Coastguard Worker // via the standard is*() predicates.
5096*9880d681SAndroid Build Coastguard Worker
5097*9880d681SAndroid Build Coastguard Worker SMLoc S = Parser.getTok().getLoc();
5098*9880d681SAndroid Build Coastguard Worker
5099*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Hash) &&
5100*9880d681SAndroid Build Coastguard Worker Parser.getTok().isNot(AsmToken::Dollar))
5101*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
5102*9880d681SAndroid Build Coastguard Worker
5103*9880d681SAndroid Build Coastguard Worker // Disambiguate the VMOV forms that can accept an FP immediate.
5104*9880d681SAndroid Build Coastguard Worker // vmov.f32 <sreg>, #imm
5105*9880d681SAndroid Build Coastguard Worker // vmov.f64 <dreg>, #imm
5106*9880d681SAndroid Build Coastguard Worker // vmov.f32 <dreg>, #imm @ vector f32x2
5107*9880d681SAndroid Build Coastguard Worker // vmov.f32 <qreg>, #imm @ vector f32x4
5108*9880d681SAndroid Build Coastguard Worker //
5109*9880d681SAndroid Build Coastguard Worker // There are also the NEON VMOV instructions which expect an
5110*9880d681SAndroid Build Coastguard Worker // integer constant. Make sure we don't try to parse an FPImm
5111*9880d681SAndroid Build Coastguard Worker // for these:
5112*9880d681SAndroid Build Coastguard Worker // vmov.i{8|16|32|64} <dreg|qreg>, #imm
5113*9880d681SAndroid Build Coastguard Worker ARMOperand &TyOp = static_cast<ARMOperand &>(*Operands[2]);
5114*9880d681SAndroid Build Coastguard Worker bool isVmovf = TyOp.isToken() &&
5115*9880d681SAndroid Build Coastguard Worker (TyOp.getToken() == ".f32" || TyOp.getToken() == ".f64" ||
5116*9880d681SAndroid Build Coastguard Worker TyOp.getToken() == ".f16");
5117*9880d681SAndroid Build Coastguard Worker ARMOperand &Mnemonic = static_cast<ARMOperand &>(*Operands[0]);
5118*9880d681SAndroid Build Coastguard Worker bool isFconst = Mnemonic.isToken() && (Mnemonic.getToken() == "fconstd" ||
5119*9880d681SAndroid Build Coastguard Worker Mnemonic.getToken() == "fconsts");
5120*9880d681SAndroid Build Coastguard Worker if (!(isVmovf || isFconst))
5121*9880d681SAndroid Build Coastguard Worker return MatchOperand_NoMatch;
5122*9880d681SAndroid Build Coastguard Worker
5123*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '#' or '$'.
5124*9880d681SAndroid Build Coastguard Worker
5125*9880d681SAndroid Build Coastguard Worker // Handle negation, as that still comes through as a separate token.
5126*9880d681SAndroid Build Coastguard Worker bool isNegative = false;
5127*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Minus)) {
5128*9880d681SAndroid Build Coastguard Worker isNegative = true;
5129*9880d681SAndroid Build Coastguard Worker Parser.Lex();
5130*9880d681SAndroid Build Coastguard Worker }
5131*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
5132*9880d681SAndroid Build Coastguard Worker SMLoc Loc = Tok.getLoc();
5133*9880d681SAndroid Build Coastguard Worker if (Tok.is(AsmToken::Real) && isVmovf) {
5134*9880d681SAndroid Build Coastguard Worker APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
5135*9880d681SAndroid Build Coastguard Worker uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
5136*9880d681SAndroid Build Coastguard Worker // If we had a '-' in front, toggle the sign bit.
5137*9880d681SAndroid Build Coastguard Worker IntVal ^= (uint64_t)isNegative << 31;
5138*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the token.
5139*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(
5140*9880d681SAndroid Build Coastguard Worker MCConstantExpr::create(IntVal, getContext()),
5141*9880d681SAndroid Build Coastguard Worker S, Parser.getTok().getLoc()));
5142*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
5143*9880d681SAndroid Build Coastguard Worker }
5144*9880d681SAndroid Build Coastguard Worker // Also handle plain integers. Instructions which allow floating point
5145*9880d681SAndroid Build Coastguard Worker // immediates also allow a raw encoded 8-bit value.
5146*9880d681SAndroid Build Coastguard Worker if (Tok.is(AsmToken::Integer) && isFconst) {
5147*9880d681SAndroid Build Coastguard Worker int64_t Val = Tok.getIntVal();
5148*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the token.
5149*9880d681SAndroid Build Coastguard Worker if (Val > 255 || Val < 0) {
5150*9880d681SAndroid Build Coastguard Worker Error(Loc, "encoded floating point value out of range");
5151*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
5152*9880d681SAndroid Build Coastguard Worker }
5153*9880d681SAndroid Build Coastguard Worker float RealVal = ARM_AM::getFPImmFloat(Val);
5154*9880d681SAndroid Build Coastguard Worker Val = APFloat(RealVal).bitcastToAPInt().getZExtValue();
5155*9880d681SAndroid Build Coastguard Worker
5156*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(
5157*9880d681SAndroid Build Coastguard Worker MCConstantExpr::create(Val, getContext()), S,
5158*9880d681SAndroid Build Coastguard Worker Parser.getTok().getLoc()));
5159*9880d681SAndroid Build Coastguard Worker return MatchOperand_Success;
5160*9880d681SAndroid Build Coastguard Worker }
5161*9880d681SAndroid Build Coastguard Worker
5162*9880d681SAndroid Build Coastguard Worker Error(Loc, "invalid floating point immediate");
5163*9880d681SAndroid Build Coastguard Worker return MatchOperand_ParseFail;
5164*9880d681SAndroid Build Coastguard Worker }
5165*9880d681SAndroid Build Coastguard Worker
5166*9880d681SAndroid Build Coastguard Worker /// Parse a arm instruction operand. For now this parses the operand regardless
5167*9880d681SAndroid Build Coastguard Worker /// of the mnemonic.
parseOperand(OperandVector & Operands,StringRef Mnemonic)5168*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
5169*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
5170*9880d681SAndroid Build Coastguard Worker SMLoc S, E;
5171*9880d681SAndroid Build Coastguard Worker
5172*9880d681SAndroid Build Coastguard Worker // Check if the current operand has a custom associated parser, if so, try to
5173*9880d681SAndroid Build Coastguard Worker // custom parse the operand, or fallback to the general approach.
5174*9880d681SAndroid Build Coastguard Worker OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5175*9880d681SAndroid Build Coastguard Worker if (ResTy == MatchOperand_Success)
5176*9880d681SAndroid Build Coastguard Worker return false;
5177*9880d681SAndroid Build Coastguard Worker // If there wasn't a custom match, try the generic matcher below. Otherwise,
5178*9880d681SAndroid Build Coastguard Worker // there was a match, but an error occurred, in which case, just return that
5179*9880d681SAndroid Build Coastguard Worker // the operand parsing failed.
5180*9880d681SAndroid Build Coastguard Worker if (ResTy == MatchOperand_ParseFail)
5181*9880d681SAndroid Build Coastguard Worker return true;
5182*9880d681SAndroid Build Coastguard Worker
5183*9880d681SAndroid Build Coastguard Worker switch (getLexer().getKind()) {
5184*9880d681SAndroid Build Coastguard Worker default:
5185*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "unexpected token in operand");
5186*9880d681SAndroid Build Coastguard Worker return true;
5187*9880d681SAndroid Build Coastguard Worker case AsmToken::Identifier: {
5188*9880d681SAndroid Build Coastguard Worker // If we've seen a branch mnemonic, the next operand must be a label. This
5189*9880d681SAndroid Build Coastguard Worker // is true even if the label is a register name. So "br r1" means branch to
5190*9880d681SAndroid Build Coastguard Worker // label "r1".
5191*9880d681SAndroid Build Coastguard Worker bool ExpectLabel = Mnemonic == "b" || Mnemonic == "bl";
5192*9880d681SAndroid Build Coastguard Worker if (!ExpectLabel) {
5193*9880d681SAndroid Build Coastguard Worker if (!tryParseRegisterWithWriteBack(Operands))
5194*9880d681SAndroid Build Coastguard Worker return false;
5195*9880d681SAndroid Build Coastguard Worker int Res = tryParseShiftRegister(Operands);
5196*9880d681SAndroid Build Coastguard Worker if (Res == 0) // success
5197*9880d681SAndroid Build Coastguard Worker return false;
5198*9880d681SAndroid Build Coastguard Worker else if (Res == -1) // irrecoverable error
5199*9880d681SAndroid Build Coastguard Worker return true;
5200*9880d681SAndroid Build Coastguard Worker // If this is VMRS, check for the apsr_nzcv operand.
5201*9880d681SAndroid Build Coastguard Worker if (Mnemonic == "vmrs" &&
5202*9880d681SAndroid Build Coastguard Worker Parser.getTok().getString().equals_lower("apsr_nzcv")) {
5203*9880d681SAndroid Build Coastguard Worker S = Parser.getTok().getLoc();
5204*9880d681SAndroid Build Coastguard Worker Parser.Lex();
5205*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
5206*9880d681SAndroid Build Coastguard Worker return false;
5207*9880d681SAndroid Build Coastguard Worker }
5208*9880d681SAndroid Build Coastguard Worker }
5209*9880d681SAndroid Build Coastguard Worker
5210*9880d681SAndroid Build Coastguard Worker // Fall though for the Identifier case that is not a register or a
5211*9880d681SAndroid Build Coastguard Worker // special name.
5212*9880d681SAndroid Build Coastguard Worker }
5213*9880d681SAndroid Build Coastguard Worker case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
5214*9880d681SAndroid Build Coastguard Worker case AsmToken::Integer: // things like 1f and 2b as a branch targets
5215*9880d681SAndroid Build Coastguard Worker case AsmToken::String: // quoted label names.
5216*9880d681SAndroid Build Coastguard Worker case AsmToken::Dot: { // . as a branch target
5217*9880d681SAndroid Build Coastguard Worker // This was not a register so parse other operands that start with an
5218*9880d681SAndroid Build Coastguard Worker // identifier (like labels) as expressions and create them as immediates.
5219*9880d681SAndroid Build Coastguard Worker const MCExpr *IdVal;
5220*9880d681SAndroid Build Coastguard Worker S = Parser.getTok().getLoc();
5221*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(IdVal))
5222*9880d681SAndroid Build Coastguard Worker return true;
5223*9880d681SAndroid Build Coastguard Worker E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5224*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
5225*9880d681SAndroid Build Coastguard Worker return false;
5226*9880d681SAndroid Build Coastguard Worker }
5227*9880d681SAndroid Build Coastguard Worker case AsmToken::LBrac:
5228*9880d681SAndroid Build Coastguard Worker return parseMemory(Operands);
5229*9880d681SAndroid Build Coastguard Worker case AsmToken::LCurly:
5230*9880d681SAndroid Build Coastguard Worker return parseRegisterList(Operands);
5231*9880d681SAndroid Build Coastguard Worker case AsmToken::Dollar:
5232*9880d681SAndroid Build Coastguard Worker case AsmToken::Hash: {
5233*9880d681SAndroid Build Coastguard Worker // #42 -> immediate.
5234*9880d681SAndroid Build Coastguard Worker S = Parser.getTok().getLoc();
5235*9880d681SAndroid Build Coastguard Worker Parser.Lex();
5236*9880d681SAndroid Build Coastguard Worker
5237*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Colon)) {
5238*9880d681SAndroid Build Coastguard Worker bool isNegative = Parser.getTok().is(AsmToken::Minus);
5239*9880d681SAndroid Build Coastguard Worker const MCExpr *ImmVal;
5240*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(ImmVal))
5241*9880d681SAndroid Build Coastguard Worker return true;
5242*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
5243*9880d681SAndroid Build Coastguard Worker if (CE) {
5244*9880d681SAndroid Build Coastguard Worker int32_t Val = CE->getValue();
5245*9880d681SAndroid Build Coastguard Worker if (isNegative && Val == 0)
5246*9880d681SAndroid Build Coastguard Worker ImmVal = MCConstantExpr::create(INT32_MIN, getContext());
5247*9880d681SAndroid Build Coastguard Worker }
5248*9880d681SAndroid Build Coastguard Worker E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5249*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
5250*9880d681SAndroid Build Coastguard Worker
5251*9880d681SAndroid Build Coastguard Worker // There can be a trailing '!' on operands that we want as a separate
5252*9880d681SAndroid Build Coastguard Worker // '!' Token operand. Handle that here. For example, the compatibility
5253*9880d681SAndroid Build Coastguard Worker // alias for 'srsdb sp!, #imm' is 'srsdb #imm!'.
5254*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Exclaim)) {
5255*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(),
5256*9880d681SAndroid Build Coastguard Worker Parser.getTok().getLoc()));
5257*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat exclaim token
5258*9880d681SAndroid Build Coastguard Worker }
5259*9880d681SAndroid Build Coastguard Worker return false;
5260*9880d681SAndroid Build Coastguard Worker }
5261*9880d681SAndroid Build Coastguard Worker // w/ a ':' after the '#', it's just like a plain ':'.
5262*9880d681SAndroid Build Coastguard Worker // FALLTHROUGH
5263*9880d681SAndroid Build Coastguard Worker }
5264*9880d681SAndroid Build Coastguard Worker case AsmToken::Colon: {
5265*9880d681SAndroid Build Coastguard Worker S = Parser.getTok().getLoc();
5266*9880d681SAndroid Build Coastguard Worker // ":lower16:" and ":upper16:" expression prefixes
5267*9880d681SAndroid Build Coastguard Worker // FIXME: Check it's an expression prefix,
5268*9880d681SAndroid Build Coastguard Worker // e.g. (FOO - :lower16:BAR) isn't legal.
5269*9880d681SAndroid Build Coastguard Worker ARMMCExpr::VariantKind RefKind;
5270*9880d681SAndroid Build Coastguard Worker if (parsePrefix(RefKind))
5271*9880d681SAndroid Build Coastguard Worker return true;
5272*9880d681SAndroid Build Coastguard Worker
5273*9880d681SAndroid Build Coastguard Worker const MCExpr *SubExprVal;
5274*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(SubExprVal))
5275*9880d681SAndroid Build Coastguard Worker return true;
5276*9880d681SAndroid Build Coastguard Worker
5277*9880d681SAndroid Build Coastguard Worker const MCExpr *ExprVal = ARMMCExpr::create(RefKind, SubExprVal,
5278*9880d681SAndroid Build Coastguard Worker getContext());
5279*9880d681SAndroid Build Coastguard Worker E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5280*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
5281*9880d681SAndroid Build Coastguard Worker return false;
5282*9880d681SAndroid Build Coastguard Worker }
5283*9880d681SAndroid Build Coastguard Worker case AsmToken::Equal: {
5284*9880d681SAndroid Build Coastguard Worker S = Parser.getTok().getLoc();
5285*9880d681SAndroid Build Coastguard Worker if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
5286*9880d681SAndroid Build Coastguard Worker return Error(S, "unexpected token in operand");
5287*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat '='
5288*9880d681SAndroid Build Coastguard Worker const MCExpr *SubExprVal;
5289*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(SubExprVal))
5290*9880d681SAndroid Build Coastguard Worker return true;
5291*9880d681SAndroid Build Coastguard Worker E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5292*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E));
5293*9880d681SAndroid Build Coastguard Worker return false;
5294*9880d681SAndroid Build Coastguard Worker }
5295*9880d681SAndroid Build Coastguard Worker }
5296*9880d681SAndroid Build Coastguard Worker }
5297*9880d681SAndroid Build Coastguard Worker
5298*9880d681SAndroid Build Coastguard Worker // parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
5299*9880d681SAndroid Build Coastguard Worker // :lower16: and :upper16:.
parsePrefix(ARMMCExpr::VariantKind & RefKind)5300*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
5301*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
5302*9880d681SAndroid Build Coastguard Worker RefKind = ARMMCExpr::VK_ARM_None;
5303*9880d681SAndroid Build Coastguard Worker
5304*9880d681SAndroid Build Coastguard Worker // consume an optional '#' (GNU compatibility)
5305*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::Hash))
5306*9880d681SAndroid Build Coastguard Worker Parser.Lex();
5307*9880d681SAndroid Build Coastguard Worker
5308*9880d681SAndroid Build Coastguard Worker // :lower16: and :upper16: modifiers
5309*9880d681SAndroid Build Coastguard Worker assert(getLexer().is(AsmToken::Colon) && "expected a :");
5310*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat ':'
5311*9880d681SAndroid Build Coastguard Worker
5312*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Identifier)) {
5313*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
5314*9880d681SAndroid Build Coastguard Worker return true;
5315*9880d681SAndroid Build Coastguard Worker }
5316*9880d681SAndroid Build Coastguard Worker
5317*9880d681SAndroid Build Coastguard Worker enum {
5318*9880d681SAndroid Build Coastguard Worker COFF = (1 << MCObjectFileInfo::IsCOFF),
5319*9880d681SAndroid Build Coastguard Worker ELF = (1 << MCObjectFileInfo::IsELF),
5320*9880d681SAndroid Build Coastguard Worker MACHO = (1 << MCObjectFileInfo::IsMachO)
5321*9880d681SAndroid Build Coastguard Worker };
5322*9880d681SAndroid Build Coastguard Worker static const struct PrefixEntry {
5323*9880d681SAndroid Build Coastguard Worker const char *Spelling;
5324*9880d681SAndroid Build Coastguard Worker ARMMCExpr::VariantKind VariantKind;
5325*9880d681SAndroid Build Coastguard Worker uint8_t SupportedFormats;
5326*9880d681SAndroid Build Coastguard Worker } PrefixEntries[] = {
5327*9880d681SAndroid Build Coastguard Worker { "lower16", ARMMCExpr::VK_ARM_LO16, COFF | ELF | MACHO },
5328*9880d681SAndroid Build Coastguard Worker { "upper16", ARMMCExpr::VK_ARM_HI16, COFF | ELF | MACHO },
5329*9880d681SAndroid Build Coastguard Worker };
5330*9880d681SAndroid Build Coastguard Worker
5331*9880d681SAndroid Build Coastguard Worker StringRef IDVal = Parser.getTok().getIdentifier();
5332*9880d681SAndroid Build Coastguard Worker
5333*9880d681SAndroid Build Coastguard Worker const auto &Prefix =
5334*9880d681SAndroid Build Coastguard Worker std::find_if(std::begin(PrefixEntries), std::end(PrefixEntries),
5335*9880d681SAndroid Build Coastguard Worker [&IDVal](const PrefixEntry &PE) {
5336*9880d681SAndroid Build Coastguard Worker return PE.Spelling == IDVal;
5337*9880d681SAndroid Build Coastguard Worker });
5338*9880d681SAndroid Build Coastguard Worker if (Prefix == std::end(PrefixEntries)) {
5339*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
5340*9880d681SAndroid Build Coastguard Worker return true;
5341*9880d681SAndroid Build Coastguard Worker }
5342*9880d681SAndroid Build Coastguard Worker
5343*9880d681SAndroid Build Coastguard Worker uint8_t CurrentFormat;
5344*9880d681SAndroid Build Coastguard Worker switch (getContext().getObjectFileInfo()->getObjectFileType()) {
5345*9880d681SAndroid Build Coastguard Worker case MCObjectFileInfo::IsMachO:
5346*9880d681SAndroid Build Coastguard Worker CurrentFormat = MACHO;
5347*9880d681SAndroid Build Coastguard Worker break;
5348*9880d681SAndroid Build Coastguard Worker case MCObjectFileInfo::IsELF:
5349*9880d681SAndroid Build Coastguard Worker CurrentFormat = ELF;
5350*9880d681SAndroid Build Coastguard Worker break;
5351*9880d681SAndroid Build Coastguard Worker case MCObjectFileInfo::IsCOFF:
5352*9880d681SAndroid Build Coastguard Worker CurrentFormat = COFF;
5353*9880d681SAndroid Build Coastguard Worker break;
5354*9880d681SAndroid Build Coastguard Worker }
5355*9880d681SAndroid Build Coastguard Worker
5356*9880d681SAndroid Build Coastguard Worker if (~Prefix->SupportedFormats & CurrentFormat) {
5357*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(),
5358*9880d681SAndroid Build Coastguard Worker "cannot represent relocation in the current file format");
5359*9880d681SAndroid Build Coastguard Worker return true;
5360*9880d681SAndroid Build Coastguard Worker }
5361*9880d681SAndroid Build Coastguard Worker
5362*9880d681SAndroid Build Coastguard Worker RefKind = Prefix->VariantKind;
5363*9880d681SAndroid Build Coastguard Worker Parser.Lex();
5364*9880d681SAndroid Build Coastguard Worker
5365*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Colon)) {
5366*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "unexpected token after prefix");
5367*9880d681SAndroid Build Coastguard Worker return true;
5368*9880d681SAndroid Build Coastguard Worker }
5369*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the last ':'
5370*9880d681SAndroid Build Coastguard Worker
5371*9880d681SAndroid Build Coastguard Worker return false;
5372*9880d681SAndroid Build Coastguard Worker }
5373*9880d681SAndroid Build Coastguard Worker
5374*9880d681SAndroid Build Coastguard Worker /// \brief Given a mnemonic, split out possible predication code and carry
5375*9880d681SAndroid Build Coastguard Worker /// setting letters to form a canonical mnemonic and flags.
5376*9880d681SAndroid Build Coastguard Worker //
5377*9880d681SAndroid Build Coastguard Worker // FIXME: Would be nice to autogen this.
5378*9880d681SAndroid Build Coastguard Worker // FIXME: This is a bit of a maze of special cases.
splitMnemonic(StringRef Mnemonic,unsigned & PredicationCode,bool & CarrySetting,unsigned & ProcessorIMod,StringRef & ITMask)5379*9880d681SAndroid Build Coastguard Worker StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
5380*9880d681SAndroid Build Coastguard Worker unsigned &PredicationCode,
5381*9880d681SAndroid Build Coastguard Worker bool &CarrySetting,
5382*9880d681SAndroid Build Coastguard Worker unsigned &ProcessorIMod,
5383*9880d681SAndroid Build Coastguard Worker StringRef &ITMask) {
5384*9880d681SAndroid Build Coastguard Worker PredicationCode = ARMCC::AL;
5385*9880d681SAndroid Build Coastguard Worker CarrySetting = false;
5386*9880d681SAndroid Build Coastguard Worker ProcessorIMod = 0;
5387*9880d681SAndroid Build Coastguard Worker
5388*9880d681SAndroid Build Coastguard Worker // Ignore some mnemonics we know aren't predicated forms.
5389*9880d681SAndroid Build Coastguard Worker //
5390*9880d681SAndroid Build Coastguard Worker // FIXME: Would be nice to autogen this.
5391*9880d681SAndroid Build Coastguard Worker if ((Mnemonic == "movs" && isThumb()) ||
5392*9880d681SAndroid Build Coastguard Worker Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
5393*9880d681SAndroid Build Coastguard Worker Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
5394*9880d681SAndroid Build Coastguard Worker Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
5395*9880d681SAndroid Build Coastguard Worker Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
5396*9880d681SAndroid Build Coastguard Worker Mnemonic == "vaclt" || Mnemonic == "vacle" || Mnemonic == "hlt" ||
5397*9880d681SAndroid Build Coastguard Worker Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
5398*9880d681SAndroid Build Coastguard Worker Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
5399*9880d681SAndroid Build Coastguard Worker Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
5400*9880d681SAndroid Build Coastguard Worker Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" ||
5401*9880d681SAndroid Build Coastguard Worker Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" ||
5402*9880d681SAndroid Build Coastguard Worker Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" ||
5403*9880d681SAndroid Build Coastguard Worker Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" ||
5404*9880d681SAndroid Build Coastguard Worker Mnemonic.startswith("vsel") || Mnemonic == "vins" || Mnemonic == "vmovx" ||
5405*9880d681SAndroid Build Coastguard Worker Mnemonic == "bxns" || Mnemonic == "blxns")
5406*9880d681SAndroid Build Coastguard Worker return Mnemonic;
5407*9880d681SAndroid Build Coastguard Worker
5408*9880d681SAndroid Build Coastguard Worker // First, split out any predication code. Ignore mnemonics we know aren't
5409*9880d681SAndroid Build Coastguard Worker // predicated but do have a carry-set and so weren't caught above.
5410*9880d681SAndroid Build Coastguard Worker if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
5411*9880d681SAndroid Build Coastguard Worker Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
5412*9880d681SAndroid Build Coastguard Worker Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
5413*9880d681SAndroid Build Coastguard Worker Mnemonic != "sbcs" && Mnemonic != "rscs") {
5414*9880d681SAndroid Build Coastguard Worker unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
5415*9880d681SAndroid Build Coastguard Worker .Case("eq", ARMCC::EQ)
5416*9880d681SAndroid Build Coastguard Worker .Case("ne", ARMCC::NE)
5417*9880d681SAndroid Build Coastguard Worker .Case("hs", ARMCC::HS)
5418*9880d681SAndroid Build Coastguard Worker .Case("cs", ARMCC::HS)
5419*9880d681SAndroid Build Coastguard Worker .Case("lo", ARMCC::LO)
5420*9880d681SAndroid Build Coastguard Worker .Case("cc", ARMCC::LO)
5421*9880d681SAndroid Build Coastguard Worker .Case("mi", ARMCC::MI)
5422*9880d681SAndroid Build Coastguard Worker .Case("pl", ARMCC::PL)
5423*9880d681SAndroid Build Coastguard Worker .Case("vs", ARMCC::VS)
5424*9880d681SAndroid Build Coastguard Worker .Case("vc", ARMCC::VC)
5425*9880d681SAndroid Build Coastguard Worker .Case("hi", ARMCC::HI)
5426*9880d681SAndroid Build Coastguard Worker .Case("ls", ARMCC::LS)
5427*9880d681SAndroid Build Coastguard Worker .Case("ge", ARMCC::GE)
5428*9880d681SAndroid Build Coastguard Worker .Case("lt", ARMCC::LT)
5429*9880d681SAndroid Build Coastguard Worker .Case("gt", ARMCC::GT)
5430*9880d681SAndroid Build Coastguard Worker .Case("le", ARMCC::LE)
5431*9880d681SAndroid Build Coastguard Worker .Case("al", ARMCC::AL)
5432*9880d681SAndroid Build Coastguard Worker .Default(~0U);
5433*9880d681SAndroid Build Coastguard Worker if (CC != ~0U) {
5434*9880d681SAndroid Build Coastguard Worker Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
5435*9880d681SAndroid Build Coastguard Worker PredicationCode = CC;
5436*9880d681SAndroid Build Coastguard Worker }
5437*9880d681SAndroid Build Coastguard Worker }
5438*9880d681SAndroid Build Coastguard Worker
5439*9880d681SAndroid Build Coastguard Worker // Next, determine if we have a carry setting bit. We explicitly ignore all
5440*9880d681SAndroid Build Coastguard Worker // the instructions we know end in 's'.
5441*9880d681SAndroid Build Coastguard Worker if (Mnemonic.endswith("s") &&
5442*9880d681SAndroid Build Coastguard Worker !(Mnemonic == "cps" || Mnemonic == "mls" ||
5443*9880d681SAndroid Build Coastguard Worker Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
5444*9880d681SAndroid Build Coastguard Worker Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
5445*9880d681SAndroid Build Coastguard Worker Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
5446*9880d681SAndroid Build Coastguard Worker Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
5447*9880d681SAndroid Build Coastguard Worker Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
5448*9880d681SAndroid Build Coastguard Worker Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
5449*9880d681SAndroid Build Coastguard Worker Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
5450*9880d681SAndroid Build Coastguard Worker Mnemonic == "vfms" || Mnemonic == "vfnms" || Mnemonic == "fconsts" ||
5451*9880d681SAndroid Build Coastguard Worker Mnemonic == "bxns" || Mnemonic == "blxns" ||
5452*9880d681SAndroid Build Coastguard Worker (Mnemonic == "movs" && isThumb()))) {
5453*9880d681SAndroid Build Coastguard Worker Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
5454*9880d681SAndroid Build Coastguard Worker CarrySetting = true;
5455*9880d681SAndroid Build Coastguard Worker }
5456*9880d681SAndroid Build Coastguard Worker
5457*9880d681SAndroid Build Coastguard Worker // The "cps" instruction can have a interrupt mode operand which is glued into
5458*9880d681SAndroid Build Coastguard Worker // the mnemonic. Check if this is the case, split it and parse the imod op
5459*9880d681SAndroid Build Coastguard Worker if (Mnemonic.startswith("cps")) {
5460*9880d681SAndroid Build Coastguard Worker // Split out any imod code.
5461*9880d681SAndroid Build Coastguard Worker unsigned IMod =
5462*9880d681SAndroid Build Coastguard Worker StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
5463*9880d681SAndroid Build Coastguard Worker .Case("ie", ARM_PROC::IE)
5464*9880d681SAndroid Build Coastguard Worker .Case("id", ARM_PROC::ID)
5465*9880d681SAndroid Build Coastguard Worker .Default(~0U);
5466*9880d681SAndroid Build Coastguard Worker if (IMod != ~0U) {
5467*9880d681SAndroid Build Coastguard Worker Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
5468*9880d681SAndroid Build Coastguard Worker ProcessorIMod = IMod;
5469*9880d681SAndroid Build Coastguard Worker }
5470*9880d681SAndroid Build Coastguard Worker }
5471*9880d681SAndroid Build Coastguard Worker
5472*9880d681SAndroid Build Coastguard Worker // The "it" instruction has the condition mask on the end of the mnemonic.
5473*9880d681SAndroid Build Coastguard Worker if (Mnemonic.startswith("it")) {
5474*9880d681SAndroid Build Coastguard Worker ITMask = Mnemonic.slice(2, Mnemonic.size());
5475*9880d681SAndroid Build Coastguard Worker Mnemonic = Mnemonic.slice(0, 2);
5476*9880d681SAndroid Build Coastguard Worker }
5477*9880d681SAndroid Build Coastguard Worker
5478*9880d681SAndroid Build Coastguard Worker return Mnemonic;
5479*9880d681SAndroid Build Coastguard Worker }
5480*9880d681SAndroid Build Coastguard Worker
5481*9880d681SAndroid Build Coastguard Worker /// \brief Given a canonical mnemonic, determine if the instruction ever allows
5482*9880d681SAndroid Build Coastguard Worker /// inclusion of carry set or predication code operands.
5483*9880d681SAndroid Build Coastguard Worker //
5484*9880d681SAndroid Build Coastguard Worker // FIXME: It would be nice to autogen this.
getMnemonicAcceptInfo(StringRef Mnemonic,StringRef FullInst,bool & CanAcceptCarrySet,bool & CanAcceptPredicationCode)5485*9880d681SAndroid Build Coastguard Worker void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst,
5486*9880d681SAndroid Build Coastguard Worker bool &CanAcceptCarrySet,
5487*9880d681SAndroid Build Coastguard Worker bool &CanAcceptPredicationCode) {
5488*9880d681SAndroid Build Coastguard Worker CanAcceptCarrySet =
5489*9880d681SAndroid Build Coastguard Worker Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
5490*9880d681SAndroid Build Coastguard Worker Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
5491*9880d681SAndroid Build Coastguard Worker Mnemonic == "add" || Mnemonic == "adc" || Mnemonic == "mul" ||
5492*9880d681SAndroid Build Coastguard Worker Mnemonic == "bic" || Mnemonic == "asr" || Mnemonic == "orr" ||
5493*9880d681SAndroid Build Coastguard Worker Mnemonic == "mvn" || Mnemonic == "rsb" || Mnemonic == "rsc" ||
5494*9880d681SAndroid Build Coastguard Worker Mnemonic == "orn" || Mnemonic == "sbc" || Mnemonic == "eor" ||
5495*9880d681SAndroid Build Coastguard Worker Mnemonic == "neg" || Mnemonic == "vfm" || Mnemonic == "vfnm" ||
5496*9880d681SAndroid Build Coastguard Worker (!isThumb() &&
5497*9880d681SAndroid Build Coastguard Worker (Mnemonic == "smull" || Mnemonic == "mov" || Mnemonic == "mla" ||
5498*9880d681SAndroid Build Coastguard Worker Mnemonic == "smlal" || Mnemonic == "umlal" || Mnemonic == "umull"));
5499*9880d681SAndroid Build Coastguard Worker
5500*9880d681SAndroid Build Coastguard Worker if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" ||
5501*9880d681SAndroid Build Coastguard Worker Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" ||
5502*9880d681SAndroid Build Coastguard Worker Mnemonic == "trap" || Mnemonic == "hlt" || Mnemonic == "udf" ||
5503*9880d681SAndroid Build Coastguard Worker Mnemonic.startswith("crc32") || Mnemonic.startswith("cps") ||
5504*9880d681SAndroid Build Coastguard Worker Mnemonic.startswith("vsel") || Mnemonic == "vmaxnm" ||
5505*9880d681SAndroid Build Coastguard Worker Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" ||
5506*9880d681SAndroid Build Coastguard Worker Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" ||
5507*9880d681SAndroid Build Coastguard Worker Mnemonic == "vrintn" || Mnemonic == "vrintp" || Mnemonic == "vrintm" ||
5508*9880d681SAndroid Build Coastguard Worker Mnemonic.startswith("aes") || Mnemonic == "hvc" || Mnemonic == "setpan" ||
5509*9880d681SAndroid Build Coastguard Worker Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") ||
5510*9880d681SAndroid Build Coastguard Worker (FullInst.startswith("vmull") && FullInst.endswith(".p64")) ||
5511*9880d681SAndroid Build Coastguard Worker Mnemonic == "vmovx" || Mnemonic == "vins") {
5512*9880d681SAndroid Build Coastguard Worker // These mnemonics are never predicable
5513*9880d681SAndroid Build Coastguard Worker CanAcceptPredicationCode = false;
5514*9880d681SAndroid Build Coastguard Worker } else if (!isThumb()) {
5515*9880d681SAndroid Build Coastguard Worker // Some instructions are only predicable in Thumb mode
5516*9880d681SAndroid Build Coastguard Worker CanAcceptPredicationCode =
5517*9880d681SAndroid Build Coastguard Worker Mnemonic != "cdp2" && Mnemonic != "clrex" && Mnemonic != "mcr2" &&
5518*9880d681SAndroid Build Coastguard Worker Mnemonic != "mcrr2" && Mnemonic != "mrc2" && Mnemonic != "mrrc2" &&
5519*9880d681SAndroid Build Coastguard Worker Mnemonic != "dmb" && Mnemonic != "dsb" && Mnemonic != "isb" &&
5520*9880d681SAndroid Build Coastguard Worker Mnemonic != "pld" && Mnemonic != "pli" && Mnemonic != "pldw" &&
5521*9880d681SAndroid Build Coastguard Worker Mnemonic != "ldc2" && Mnemonic != "ldc2l" && Mnemonic != "stc2" &&
5522*9880d681SAndroid Build Coastguard Worker Mnemonic != "stc2l" && !Mnemonic.startswith("rfe") &&
5523*9880d681SAndroid Build Coastguard Worker !Mnemonic.startswith("srs");
5524*9880d681SAndroid Build Coastguard Worker } else if (isThumbOne()) {
5525*9880d681SAndroid Build Coastguard Worker if (hasV6MOps())
5526*9880d681SAndroid Build Coastguard Worker CanAcceptPredicationCode = Mnemonic != "movs";
5527*9880d681SAndroid Build Coastguard Worker else
5528*9880d681SAndroid Build Coastguard Worker CanAcceptPredicationCode = Mnemonic != "nop" && Mnemonic != "movs";
5529*9880d681SAndroid Build Coastguard Worker } else
5530*9880d681SAndroid Build Coastguard Worker CanAcceptPredicationCode = true;
5531*9880d681SAndroid Build Coastguard Worker }
5532*9880d681SAndroid Build Coastguard Worker
5533*9880d681SAndroid Build Coastguard Worker // \brief Some Thumb instructions have two operand forms that are not
5534*9880d681SAndroid Build Coastguard Worker // available as three operand, convert to two operand form if possible.
5535*9880d681SAndroid Build Coastguard Worker //
5536*9880d681SAndroid Build Coastguard Worker // FIXME: We would really like to be able to tablegen'erate this.
tryConvertingToTwoOperandForm(StringRef Mnemonic,bool CarrySetting,OperandVector & Operands)5537*9880d681SAndroid Build Coastguard Worker void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic,
5538*9880d681SAndroid Build Coastguard Worker bool CarrySetting,
5539*9880d681SAndroid Build Coastguard Worker OperandVector &Operands) {
5540*9880d681SAndroid Build Coastguard Worker if (Operands.size() != 6)
5541*9880d681SAndroid Build Coastguard Worker return;
5542*9880d681SAndroid Build Coastguard Worker
5543*9880d681SAndroid Build Coastguard Worker const auto &Op3 = static_cast<ARMOperand &>(*Operands[3]);
5544*9880d681SAndroid Build Coastguard Worker auto &Op4 = static_cast<ARMOperand &>(*Operands[4]);
5545*9880d681SAndroid Build Coastguard Worker if (!Op3.isReg() || !Op4.isReg())
5546*9880d681SAndroid Build Coastguard Worker return;
5547*9880d681SAndroid Build Coastguard Worker
5548*9880d681SAndroid Build Coastguard Worker auto Op3Reg = Op3.getReg();
5549*9880d681SAndroid Build Coastguard Worker auto Op4Reg = Op4.getReg();
5550*9880d681SAndroid Build Coastguard Worker
5551*9880d681SAndroid Build Coastguard Worker // For most Thumb2 cases we just generate the 3 operand form and reduce
5552*9880d681SAndroid Build Coastguard Worker // it in processInstruction(), but the 3 operand form of ADD (t2ADDrr)
5553*9880d681SAndroid Build Coastguard Worker // won't accept SP or PC so we do the transformation here taking care
5554*9880d681SAndroid Build Coastguard Worker // with immediate range in the 'add sp, sp #imm' case.
5555*9880d681SAndroid Build Coastguard Worker auto &Op5 = static_cast<ARMOperand &>(*Operands[5]);
5556*9880d681SAndroid Build Coastguard Worker if (isThumbTwo()) {
5557*9880d681SAndroid Build Coastguard Worker if (Mnemonic != "add")
5558*9880d681SAndroid Build Coastguard Worker return;
5559*9880d681SAndroid Build Coastguard Worker bool TryTransform = Op3Reg == ARM::PC || Op4Reg == ARM::PC ||
5560*9880d681SAndroid Build Coastguard Worker (Op5.isReg() && Op5.getReg() == ARM::PC);
5561*9880d681SAndroid Build Coastguard Worker if (!TryTransform) {
5562*9880d681SAndroid Build Coastguard Worker TryTransform = (Op3Reg == ARM::SP || Op4Reg == ARM::SP ||
5563*9880d681SAndroid Build Coastguard Worker (Op5.isReg() && Op5.getReg() == ARM::SP)) &&
5564*9880d681SAndroid Build Coastguard Worker !(Op3Reg == ARM::SP && Op4Reg == ARM::SP &&
5565*9880d681SAndroid Build Coastguard Worker Op5.isImm() && !Op5.isImm0_508s4());
5566*9880d681SAndroid Build Coastguard Worker }
5567*9880d681SAndroid Build Coastguard Worker if (!TryTransform)
5568*9880d681SAndroid Build Coastguard Worker return;
5569*9880d681SAndroid Build Coastguard Worker } else if (!isThumbOne())
5570*9880d681SAndroid Build Coastguard Worker return;
5571*9880d681SAndroid Build Coastguard Worker
5572*9880d681SAndroid Build Coastguard Worker if (!(Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" ||
5573*9880d681SAndroid Build Coastguard Worker Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
5574*9880d681SAndroid Build Coastguard Worker Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" ||
5575*9880d681SAndroid Build Coastguard Worker Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic"))
5576*9880d681SAndroid Build Coastguard Worker return;
5577*9880d681SAndroid Build Coastguard Worker
5578*9880d681SAndroid Build Coastguard Worker // If first 2 operands of a 3 operand instruction are the same
5579*9880d681SAndroid Build Coastguard Worker // then transform to 2 operand version of the same instruction
5580*9880d681SAndroid Build Coastguard Worker // e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1'
5581*9880d681SAndroid Build Coastguard Worker bool Transform = Op3Reg == Op4Reg;
5582*9880d681SAndroid Build Coastguard Worker
5583*9880d681SAndroid Build Coastguard Worker // For communtative operations, we might be able to transform if we swap
5584*9880d681SAndroid Build Coastguard Worker // Op4 and Op5. The 'ADD Rdm, SP, Rdm' form is already handled specially
5585*9880d681SAndroid Build Coastguard Worker // as tADDrsp.
5586*9880d681SAndroid Build Coastguard Worker const ARMOperand *LastOp = &Op5;
5587*9880d681SAndroid Build Coastguard Worker bool Swap = false;
5588*9880d681SAndroid Build Coastguard Worker if (!Transform && Op5.isReg() && Op3Reg == Op5.getReg() &&
5589*9880d681SAndroid Build Coastguard Worker ((Mnemonic == "add" && Op4Reg != ARM::SP) ||
5590*9880d681SAndroid Build Coastguard Worker Mnemonic == "and" || Mnemonic == "eor" ||
5591*9880d681SAndroid Build Coastguard Worker Mnemonic == "adc" || Mnemonic == "orr")) {
5592*9880d681SAndroid Build Coastguard Worker Swap = true;
5593*9880d681SAndroid Build Coastguard Worker LastOp = &Op4;
5594*9880d681SAndroid Build Coastguard Worker Transform = true;
5595*9880d681SAndroid Build Coastguard Worker }
5596*9880d681SAndroid Build Coastguard Worker
5597*9880d681SAndroid Build Coastguard Worker // If both registers are the same then remove one of them from
5598*9880d681SAndroid Build Coastguard Worker // the operand list, with certain exceptions.
5599*9880d681SAndroid Build Coastguard Worker if (Transform) {
5600*9880d681SAndroid Build Coastguard Worker // Don't transform 'adds Rd, Rd, Rm' or 'sub{s} Rd, Rd, Rm' because the
5601*9880d681SAndroid Build Coastguard Worker // 2 operand forms don't exist.
5602*9880d681SAndroid Build Coastguard Worker if (((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub") &&
5603*9880d681SAndroid Build Coastguard Worker LastOp->isReg())
5604*9880d681SAndroid Build Coastguard Worker Transform = false;
5605*9880d681SAndroid Build Coastguard Worker
5606*9880d681SAndroid Build Coastguard Worker // Don't transform 'add/sub{s} Rd, Rd, #imm' if the immediate fits into
5607*9880d681SAndroid Build Coastguard Worker // 3-bits because the ARMARM says not to.
5608*9880d681SAndroid Build Coastguard Worker if ((Mnemonic == "add" || Mnemonic == "sub") && LastOp->isImm0_7())
5609*9880d681SAndroid Build Coastguard Worker Transform = false;
5610*9880d681SAndroid Build Coastguard Worker }
5611*9880d681SAndroid Build Coastguard Worker
5612*9880d681SAndroid Build Coastguard Worker if (Transform) {
5613*9880d681SAndroid Build Coastguard Worker if (Swap)
5614*9880d681SAndroid Build Coastguard Worker std::swap(Op4, Op5);
5615*9880d681SAndroid Build Coastguard Worker Operands.erase(Operands.begin() + 3);
5616*9880d681SAndroid Build Coastguard Worker }
5617*9880d681SAndroid Build Coastguard Worker }
5618*9880d681SAndroid Build Coastguard Worker
shouldOmitCCOutOperand(StringRef Mnemonic,OperandVector & Operands)5619*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
5620*9880d681SAndroid Build Coastguard Worker OperandVector &Operands) {
5621*9880d681SAndroid Build Coastguard Worker // FIXME: This is all horribly hacky. We really need a better way to deal
5622*9880d681SAndroid Build Coastguard Worker // with optional operands like this in the matcher table.
5623*9880d681SAndroid Build Coastguard Worker
5624*9880d681SAndroid Build Coastguard Worker // The 'mov' mnemonic is special. One variant has a cc_out operand, while
5625*9880d681SAndroid Build Coastguard Worker // another does not. Specifically, the MOVW instruction does not. So we
5626*9880d681SAndroid Build Coastguard Worker // special case it here and remove the defaulted (non-setting) cc_out
5627*9880d681SAndroid Build Coastguard Worker // operand if that's the instruction we're trying to match.
5628*9880d681SAndroid Build Coastguard Worker //
5629*9880d681SAndroid Build Coastguard Worker // We do this as post-processing of the explicit operands rather than just
5630*9880d681SAndroid Build Coastguard Worker // conditionally adding the cc_out in the first place because we need
5631*9880d681SAndroid Build Coastguard Worker // to check the type of the parsed immediate operand.
5632*9880d681SAndroid Build Coastguard Worker if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
5633*9880d681SAndroid Build Coastguard Worker !static_cast<ARMOperand &>(*Operands[4]).isModImm() &&
5634*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).isImm0_65535Expr() &&
5635*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[1]).getReg() == 0)
5636*9880d681SAndroid Build Coastguard Worker return true;
5637*9880d681SAndroid Build Coastguard Worker
5638*9880d681SAndroid Build Coastguard Worker // Register-register 'add' for thumb does not have a cc_out operand
5639*9880d681SAndroid Build Coastguard Worker // when there are only two register operands.
5640*9880d681SAndroid Build Coastguard Worker if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
5641*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5642*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5643*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[1]).getReg() == 0)
5644*9880d681SAndroid Build Coastguard Worker return true;
5645*9880d681SAndroid Build Coastguard Worker // Register-register 'add' for thumb does not have a cc_out operand
5646*9880d681SAndroid Build Coastguard Worker // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
5647*9880d681SAndroid Build Coastguard Worker // have to check the immediate range here since Thumb2 has a variant
5648*9880d681SAndroid Build Coastguard Worker // that can handle a different range and has a cc_out operand.
5649*9880d681SAndroid Build Coastguard Worker if (((isThumb() && Mnemonic == "add") ||
5650*9880d681SAndroid Build Coastguard Worker (isThumbTwo() && Mnemonic == "sub")) &&
5651*9880d681SAndroid Build Coastguard Worker Operands.size() == 6 && static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5652*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5653*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).getReg() == ARM::SP &&
5654*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 &&
5655*9880d681SAndroid Build Coastguard Worker ((Mnemonic == "add" && static_cast<ARMOperand &>(*Operands[5]).isReg()) ||
5656*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[5]).isImm0_1020s4()))
5657*9880d681SAndroid Build Coastguard Worker return true;
5658*9880d681SAndroid Build Coastguard Worker // For Thumb2, add/sub immediate does not have a cc_out operand for the
5659*9880d681SAndroid Build Coastguard Worker // imm0_4095 variant. That's the least-preferred variant when
5660*9880d681SAndroid Build Coastguard Worker // selecting via the generic "add" mnemonic, so to know that we
5661*9880d681SAndroid Build Coastguard Worker // should remove the cc_out operand, we have to explicitly check that
5662*9880d681SAndroid Build Coastguard Worker // it's not one of the other variants. Ugh.
5663*9880d681SAndroid Build Coastguard Worker if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
5664*9880d681SAndroid Build Coastguard Worker Operands.size() == 6 && static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5665*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5666*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[5]).isImm()) {
5667*9880d681SAndroid Build Coastguard Worker // Nest conditions rather than one big 'if' statement for readability.
5668*9880d681SAndroid Build Coastguard Worker //
5669*9880d681SAndroid Build Coastguard Worker // If both registers are low, we're in an IT block, and the immediate is
5670*9880d681SAndroid Build Coastguard Worker // in range, we should use encoding T1 instead, which has a cc_out.
5671*9880d681SAndroid Build Coastguard Worker if (inITBlock() &&
5672*9880d681SAndroid Build Coastguard Worker isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg()) &&
5673*9880d681SAndroid Build Coastguard Worker isARMLowRegister(static_cast<ARMOperand &>(*Operands[4]).getReg()) &&
5674*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[5]).isImm0_7())
5675*9880d681SAndroid Build Coastguard Worker return false;
5676*9880d681SAndroid Build Coastguard Worker // Check against T3. If the second register is the PC, this is an
5677*9880d681SAndroid Build Coastguard Worker // alternate form of ADR, which uses encoding T4, so check for that too.
5678*9880d681SAndroid Build Coastguard Worker if (static_cast<ARMOperand &>(*Operands[4]).getReg() != ARM::PC &&
5679*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[5]).isT2SOImm())
5680*9880d681SAndroid Build Coastguard Worker return false;
5681*9880d681SAndroid Build Coastguard Worker
5682*9880d681SAndroid Build Coastguard Worker // Otherwise, we use encoding T4, which does not have a cc_out
5683*9880d681SAndroid Build Coastguard Worker // operand.
5684*9880d681SAndroid Build Coastguard Worker return true;
5685*9880d681SAndroid Build Coastguard Worker }
5686*9880d681SAndroid Build Coastguard Worker
5687*9880d681SAndroid Build Coastguard Worker // The thumb2 multiply instruction doesn't have a CCOut register, so
5688*9880d681SAndroid Build Coastguard Worker // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
5689*9880d681SAndroid Build Coastguard Worker // use the 16-bit encoding or not.
5690*9880d681SAndroid Build Coastguard Worker if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
5691*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 &&
5692*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5693*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5694*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[5]).isReg() &&
5695*9880d681SAndroid Build Coastguard Worker // If the registers aren't low regs, the destination reg isn't the
5696*9880d681SAndroid Build Coastguard Worker // same as one of the source regs, or the cc_out operand is zero
5697*9880d681SAndroid Build Coastguard Worker // outside of an IT block, we have to use the 32-bit encoding, so
5698*9880d681SAndroid Build Coastguard Worker // remove the cc_out operand.
5699*9880d681SAndroid Build Coastguard Worker (!isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg()) ||
5700*9880d681SAndroid Build Coastguard Worker !isARMLowRegister(static_cast<ARMOperand &>(*Operands[4]).getReg()) ||
5701*9880d681SAndroid Build Coastguard Worker !isARMLowRegister(static_cast<ARMOperand &>(*Operands[5]).getReg()) ||
5702*9880d681SAndroid Build Coastguard Worker !inITBlock() || (static_cast<ARMOperand &>(*Operands[3]).getReg() !=
5703*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[5]).getReg() &&
5704*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).getReg() !=
5705*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).getReg())))
5706*9880d681SAndroid Build Coastguard Worker return true;
5707*9880d681SAndroid Build Coastguard Worker
5708*9880d681SAndroid Build Coastguard Worker // Also check the 'mul' syntax variant that doesn't specify an explicit
5709*9880d681SAndroid Build Coastguard Worker // destination register.
5710*9880d681SAndroid Build Coastguard Worker if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
5711*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 &&
5712*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5713*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5714*9880d681SAndroid Build Coastguard Worker // If the registers aren't low regs or the cc_out operand is zero
5715*9880d681SAndroid Build Coastguard Worker // outside of an IT block, we have to use the 32-bit encoding, so
5716*9880d681SAndroid Build Coastguard Worker // remove the cc_out operand.
5717*9880d681SAndroid Build Coastguard Worker (!isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg()) ||
5718*9880d681SAndroid Build Coastguard Worker !isARMLowRegister(static_cast<ARMOperand &>(*Operands[4]).getReg()) ||
5719*9880d681SAndroid Build Coastguard Worker !inITBlock()))
5720*9880d681SAndroid Build Coastguard Worker return true;
5721*9880d681SAndroid Build Coastguard Worker
5722*9880d681SAndroid Build Coastguard Worker
5723*9880d681SAndroid Build Coastguard Worker
5724*9880d681SAndroid Build Coastguard Worker // Register-register 'add/sub' for thumb does not have a cc_out operand
5725*9880d681SAndroid Build Coastguard Worker // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
5726*9880d681SAndroid Build Coastguard Worker // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
5727*9880d681SAndroid Build Coastguard Worker // right, this will result in better diagnostics (which operand is off)
5728*9880d681SAndroid Build Coastguard Worker // anyway.
5729*9880d681SAndroid Build Coastguard Worker if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
5730*9880d681SAndroid Build Coastguard Worker (Operands.size() == 5 || Operands.size() == 6) &&
5731*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5732*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).getReg() == ARM::SP &&
5733*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 &&
5734*9880d681SAndroid Build Coastguard Worker (static_cast<ARMOperand &>(*Operands[4]).isImm() ||
5735*9880d681SAndroid Build Coastguard Worker (Operands.size() == 6 &&
5736*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[5]).isImm())))
5737*9880d681SAndroid Build Coastguard Worker return true;
5738*9880d681SAndroid Build Coastguard Worker
5739*9880d681SAndroid Build Coastguard Worker return false;
5740*9880d681SAndroid Build Coastguard Worker }
5741*9880d681SAndroid Build Coastguard Worker
shouldOmitPredicateOperand(StringRef Mnemonic,OperandVector & Operands)5742*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::shouldOmitPredicateOperand(StringRef Mnemonic,
5743*9880d681SAndroid Build Coastguard Worker OperandVector &Operands) {
5744*9880d681SAndroid Build Coastguard Worker // VRINT{Z, R, X} have a predicate operand in VFP, but not in NEON
5745*9880d681SAndroid Build Coastguard Worker unsigned RegIdx = 3;
5746*9880d681SAndroid Build Coastguard Worker if ((Mnemonic == "vrintz" || Mnemonic == "vrintx" || Mnemonic == "vrintr") &&
5747*9880d681SAndroid Build Coastguard Worker (static_cast<ARMOperand &>(*Operands[2]).getToken() == ".f32" ||
5748*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[2]).getToken() == ".f16")) {
5749*9880d681SAndroid Build Coastguard Worker if (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
5750*9880d681SAndroid Build Coastguard Worker (static_cast<ARMOperand &>(*Operands[3]).getToken() == ".f32" ||
5751*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).getToken() == ".f16"))
5752*9880d681SAndroid Build Coastguard Worker RegIdx = 4;
5753*9880d681SAndroid Build Coastguard Worker
5754*9880d681SAndroid Build Coastguard Worker if (static_cast<ARMOperand &>(*Operands[RegIdx]).isReg() &&
5755*9880d681SAndroid Build Coastguard Worker (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(
5756*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[RegIdx]).getReg()) ||
5757*9880d681SAndroid Build Coastguard Worker ARMMCRegisterClasses[ARM::QPRRegClassID].contains(
5758*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[RegIdx]).getReg())))
5759*9880d681SAndroid Build Coastguard Worker return true;
5760*9880d681SAndroid Build Coastguard Worker }
5761*9880d681SAndroid Build Coastguard Worker return false;
5762*9880d681SAndroid Build Coastguard Worker }
5763*9880d681SAndroid Build Coastguard Worker
isDataTypeToken(StringRef Tok)5764*9880d681SAndroid Build Coastguard Worker static bool isDataTypeToken(StringRef Tok) {
5765*9880d681SAndroid Build Coastguard Worker return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
5766*9880d681SAndroid Build Coastguard Worker Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
5767*9880d681SAndroid Build Coastguard Worker Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
5768*9880d681SAndroid Build Coastguard Worker Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
5769*9880d681SAndroid Build Coastguard Worker Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
5770*9880d681SAndroid Build Coastguard Worker Tok == ".f" || Tok == ".d";
5771*9880d681SAndroid Build Coastguard Worker }
5772*9880d681SAndroid Build Coastguard Worker
5773*9880d681SAndroid Build Coastguard Worker // FIXME: This bit should probably be handled via an explicit match class
5774*9880d681SAndroid Build Coastguard Worker // in the .td files that matches the suffix instead of having it be
5775*9880d681SAndroid Build Coastguard Worker // a literal string token the way it is now.
doesIgnoreDataTypeSuffix(StringRef Mnemonic,StringRef DT)5776*9880d681SAndroid Build Coastguard Worker static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
5777*9880d681SAndroid Build Coastguard Worker return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
5778*9880d681SAndroid Build Coastguard Worker }
5779*9880d681SAndroid Build Coastguard Worker static void applyMnemonicAliases(StringRef &Mnemonic, uint64_t Features,
5780*9880d681SAndroid Build Coastguard Worker unsigned VariantID);
5781*9880d681SAndroid Build Coastguard Worker
RequiresVFPRegListValidation(StringRef Inst,bool & AcceptSinglePrecisionOnly,bool & AcceptDoublePrecisionOnly)5782*9880d681SAndroid Build Coastguard Worker static bool RequiresVFPRegListValidation(StringRef Inst,
5783*9880d681SAndroid Build Coastguard Worker bool &AcceptSinglePrecisionOnly,
5784*9880d681SAndroid Build Coastguard Worker bool &AcceptDoublePrecisionOnly) {
5785*9880d681SAndroid Build Coastguard Worker if (Inst.size() < 7)
5786*9880d681SAndroid Build Coastguard Worker return false;
5787*9880d681SAndroid Build Coastguard Worker
5788*9880d681SAndroid Build Coastguard Worker if (Inst.startswith("fldm") || Inst.startswith("fstm")) {
5789*9880d681SAndroid Build Coastguard Worker StringRef AddressingMode = Inst.substr(4, 2);
5790*9880d681SAndroid Build Coastguard Worker if (AddressingMode == "ia" || AddressingMode == "db" ||
5791*9880d681SAndroid Build Coastguard Worker AddressingMode == "ea" || AddressingMode == "fd") {
5792*9880d681SAndroid Build Coastguard Worker AcceptSinglePrecisionOnly = Inst[6] == 's';
5793*9880d681SAndroid Build Coastguard Worker AcceptDoublePrecisionOnly = Inst[6] == 'd' || Inst[6] == 'x';
5794*9880d681SAndroid Build Coastguard Worker return true;
5795*9880d681SAndroid Build Coastguard Worker }
5796*9880d681SAndroid Build Coastguard Worker }
5797*9880d681SAndroid Build Coastguard Worker
5798*9880d681SAndroid Build Coastguard Worker return false;
5799*9880d681SAndroid Build Coastguard Worker }
5800*9880d681SAndroid Build Coastguard Worker
5801*9880d681SAndroid Build Coastguard Worker /// Parse an arm instruction mnemonic followed by its operands.
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)5802*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5803*9880d681SAndroid Build Coastguard Worker SMLoc NameLoc, OperandVector &Operands) {
5804*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
5805*9880d681SAndroid Build Coastguard Worker // FIXME: Can this be done via tablegen in some fashion?
5806*9880d681SAndroid Build Coastguard Worker bool RequireVFPRegisterListCheck;
5807*9880d681SAndroid Build Coastguard Worker bool AcceptSinglePrecisionOnly;
5808*9880d681SAndroid Build Coastguard Worker bool AcceptDoublePrecisionOnly;
5809*9880d681SAndroid Build Coastguard Worker RequireVFPRegisterListCheck =
5810*9880d681SAndroid Build Coastguard Worker RequiresVFPRegListValidation(Name, AcceptSinglePrecisionOnly,
5811*9880d681SAndroid Build Coastguard Worker AcceptDoublePrecisionOnly);
5812*9880d681SAndroid Build Coastguard Worker
5813*9880d681SAndroid Build Coastguard Worker // Apply mnemonic aliases before doing anything else, as the destination
5814*9880d681SAndroid Build Coastguard Worker // mnemonic may include suffices and we want to handle them normally.
5815*9880d681SAndroid Build Coastguard Worker // The generic tblgen'erated code does this later, at the start of
5816*9880d681SAndroid Build Coastguard Worker // MatchInstructionImpl(), but that's too late for aliases that include
5817*9880d681SAndroid Build Coastguard Worker // any sort of suffix.
5818*9880d681SAndroid Build Coastguard Worker uint64_t AvailableFeatures = getAvailableFeatures();
5819*9880d681SAndroid Build Coastguard Worker unsigned AssemblerDialect = getParser().getAssemblerDialect();
5820*9880d681SAndroid Build Coastguard Worker applyMnemonicAliases(Name, AvailableFeatures, AssemblerDialect);
5821*9880d681SAndroid Build Coastguard Worker
5822*9880d681SAndroid Build Coastguard Worker // First check for the ARM-specific .req directive.
5823*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Identifier) &&
5824*9880d681SAndroid Build Coastguard Worker Parser.getTok().getIdentifier() == ".req") {
5825*9880d681SAndroid Build Coastguard Worker parseDirectiveReq(Name, NameLoc);
5826*9880d681SAndroid Build Coastguard Worker // We always return 'error' for this, as we're done with this
5827*9880d681SAndroid Build Coastguard Worker // statement and don't need to match the 'instruction."
5828*9880d681SAndroid Build Coastguard Worker return true;
5829*9880d681SAndroid Build Coastguard Worker }
5830*9880d681SAndroid Build Coastguard Worker
5831*9880d681SAndroid Build Coastguard Worker // Create the leading tokens for the mnemonic, split by '.' characters.
5832*9880d681SAndroid Build Coastguard Worker size_t Start = 0, Next = Name.find('.');
5833*9880d681SAndroid Build Coastguard Worker StringRef Mnemonic = Name.slice(Start, Next);
5834*9880d681SAndroid Build Coastguard Worker
5835*9880d681SAndroid Build Coastguard Worker // Split out the predication code and carry setting flag from the mnemonic.
5836*9880d681SAndroid Build Coastguard Worker unsigned PredicationCode;
5837*9880d681SAndroid Build Coastguard Worker unsigned ProcessorIMod;
5838*9880d681SAndroid Build Coastguard Worker bool CarrySetting;
5839*9880d681SAndroid Build Coastguard Worker StringRef ITMask;
5840*9880d681SAndroid Build Coastguard Worker Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
5841*9880d681SAndroid Build Coastguard Worker ProcessorIMod, ITMask);
5842*9880d681SAndroid Build Coastguard Worker
5843*9880d681SAndroid Build Coastguard Worker // In Thumb1, only the branch (B) instruction can be predicated.
5844*9880d681SAndroid Build Coastguard Worker if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
5845*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
5846*9880d681SAndroid Build Coastguard Worker return Error(NameLoc, "conditional execution not supported in Thumb1");
5847*9880d681SAndroid Build Coastguard Worker }
5848*9880d681SAndroid Build Coastguard Worker
5849*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
5850*9880d681SAndroid Build Coastguard Worker
5851*9880d681SAndroid Build Coastguard Worker // Handle the IT instruction ITMask. Convert it to a bitmask. This
5852*9880d681SAndroid Build Coastguard Worker // is the mask as it will be for the IT encoding if the conditional
5853*9880d681SAndroid Build Coastguard Worker // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
5854*9880d681SAndroid Build Coastguard Worker // where the conditional bit0 is zero, the instruction post-processing
5855*9880d681SAndroid Build Coastguard Worker // will adjust the mask accordingly.
5856*9880d681SAndroid Build Coastguard Worker if (Mnemonic == "it") {
5857*9880d681SAndroid Build Coastguard Worker SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
5858*9880d681SAndroid Build Coastguard Worker if (ITMask.size() > 3) {
5859*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
5860*9880d681SAndroid Build Coastguard Worker return Error(Loc, "too many conditions on IT instruction");
5861*9880d681SAndroid Build Coastguard Worker }
5862*9880d681SAndroid Build Coastguard Worker unsigned Mask = 8;
5863*9880d681SAndroid Build Coastguard Worker for (unsigned i = ITMask.size(); i != 0; --i) {
5864*9880d681SAndroid Build Coastguard Worker char pos = ITMask[i - 1];
5865*9880d681SAndroid Build Coastguard Worker if (pos != 't' && pos != 'e') {
5866*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
5867*9880d681SAndroid Build Coastguard Worker return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
5868*9880d681SAndroid Build Coastguard Worker }
5869*9880d681SAndroid Build Coastguard Worker Mask >>= 1;
5870*9880d681SAndroid Build Coastguard Worker if (ITMask[i - 1] == 't')
5871*9880d681SAndroid Build Coastguard Worker Mask |= 8;
5872*9880d681SAndroid Build Coastguard Worker }
5873*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
5874*9880d681SAndroid Build Coastguard Worker }
5875*9880d681SAndroid Build Coastguard Worker
5876*9880d681SAndroid Build Coastguard Worker // FIXME: This is all a pretty gross hack. We should automatically handle
5877*9880d681SAndroid Build Coastguard Worker // optional operands like this via tblgen.
5878*9880d681SAndroid Build Coastguard Worker
5879*9880d681SAndroid Build Coastguard Worker // Next, add the CCOut and ConditionCode operands, if needed.
5880*9880d681SAndroid Build Coastguard Worker //
5881*9880d681SAndroid Build Coastguard Worker // For mnemonics which can ever incorporate a carry setting bit or predication
5882*9880d681SAndroid Build Coastguard Worker // code, our matching model involves us always generating CCOut and
5883*9880d681SAndroid Build Coastguard Worker // ConditionCode operands to match the mnemonic "as written" and then we let
5884*9880d681SAndroid Build Coastguard Worker // the matcher deal with finding the right instruction or generating an
5885*9880d681SAndroid Build Coastguard Worker // appropriate error.
5886*9880d681SAndroid Build Coastguard Worker bool CanAcceptCarrySet, CanAcceptPredicationCode;
5887*9880d681SAndroid Build Coastguard Worker getMnemonicAcceptInfo(Mnemonic, Name, CanAcceptCarrySet, CanAcceptPredicationCode);
5888*9880d681SAndroid Build Coastguard Worker
5889*9880d681SAndroid Build Coastguard Worker // If we had a carry-set on an instruction that can't do that, issue an
5890*9880d681SAndroid Build Coastguard Worker // error.
5891*9880d681SAndroid Build Coastguard Worker if (!CanAcceptCarrySet && CarrySetting) {
5892*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
5893*9880d681SAndroid Build Coastguard Worker return Error(NameLoc, "instruction '" + Mnemonic +
5894*9880d681SAndroid Build Coastguard Worker "' can not set flags, but 's' suffix specified");
5895*9880d681SAndroid Build Coastguard Worker }
5896*9880d681SAndroid Build Coastguard Worker // If we had a predication code on an instruction that can't do that, issue an
5897*9880d681SAndroid Build Coastguard Worker // error.
5898*9880d681SAndroid Build Coastguard Worker if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
5899*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
5900*9880d681SAndroid Build Coastguard Worker return Error(NameLoc, "instruction '" + Mnemonic +
5901*9880d681SAndroid Build Coastguard Worker "' is not predicable, but condition code specified");
5902*9880d681SAndroid Build Coastguard Worker }
5903*9880d681SAndroid Build Coastguard Worker
5904*9880d681SAndroid Build Coastguard Worker // Add the carry setting operand, if necessary.
5905*9880d681SAndroid Build Coastguard Worker if (CanAcceptCarrySet) {
5906*9880d681SAndroid Build Coastguard Worker SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
5907*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
5908*9880d681SAndroid Build Coastguard Worker Loc));
5909*9880d681SAndroid Build Coastguard Worker }
5910*9880d681SAndroid Build Coastguard Worker
5911*9880d681SAndroid Build Coastguard Worker // Add the predication code operand, if necessary.
5912*9880d681SAndroid Build Coastguard Worker if (CanAcceptPredicationCode) {
5913*9880d681SAndroid Build Coastguard Worker SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
5914*9880d681SAndroid Build Coastguard Worker CarrySetting);
5915*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateCondCode(
5916*9880d681SAndroid Build Coastguard Worker ARMCC::CondCodes(PredicationCode), Loc));
5917*9880d681SAndroid Build Coastguard Worker }
5918*9880d681SAndroid Build Coastguard Worker
5919*9880d681SAndroid Build Coastguard Worker // Add the processor imod operand, if necessary.
5920*9880d681SAndroid Build Coastguard Worker if (ProcessorIMod) {
5921*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateImm(
5922*9880d681SAndroid Build Coastguard Worker MCConstantExpr::create(ProcessorIMod, getContext()),
5923*9880d681SAndroid Build Coastguard Worker NameLoc, NameLoc));
5924*9880d681SAndroid Build Coastguard Worker } else if (Mnemonic == "cps" && isMClass()) {
5925*9880d681SAndroid Build Coastguard Worker return Error(NameLoc, "instruction 'cps' requires effect for M-class");
5926*9880d681SAndroid Build Coastguard Worker }
5927*9880d681SAndroid Build Coastguard Worker
5928*9880d681SAndroid Build Coastguard Worker // Add the remaining tokens in the mnemonic.
5929*9880d681SAndroid Build Coastguard Worker while (Next != StringRef::npos) {
5930*9880d681SAndroid Build Coastguard Worker Start = Next;
5931*9880d681SAndroid Build Coastguard Worker Next = Name.find('.', Start + 1);
5932*9880d681SAndroid Build Coastguard Worker StringRef ExtraToken = Name.slice(Start, Next);
5933*9880d681SAndroid Build Coastguard Worker
5934*9880d681SAndroid Build Coastguard Worker // Some NEON instructions have an optional datatype suffix that is
5935*9880d681SAndroid Build Coastguard Worker // completely ignored. Check for that.
5936*9880d681SAndroid Build Coastguard Worker if (isDataTypeToken(ExtraToken) &&
5937*9880d681SAndroid Build Coastguard Worker doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
5938*9880d681SAndroid Build Coastguard Worker continue;
5939*9880d681SAndroid Build Coastguard Worker
5940*9880d681SAndroid Build Coastguard Worker // For for ARM mode generate an error if the .n qualifier is used.
5941*9880d681SAndroid Build Coastguard Worker if (ExtraToken == ".n" && !isThumb()) {
5942*9880d681SAndroid Build Coastguard Worker SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5943*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
5944*9880d681SAndroid Build Coastguard Worker return Error(Loc, "instruction with .n (narrow) qualifier not allowed in "
5945*9880d681SAndroid Build Coastguard Worker "arm mode");
5946*9880d681SAndroid Build Coastguard Worker }
5947*9880d681SAndroid Build Coastguard Worker
5948*9880d681SAndroid Build Coastguard Worker // The .n qualifier is always discarded as that is what the tables
5949*9880d681SAndroid Build Coastguard Worker // and matcher expect. In ARM mode the .w qualifier has no effect,
5950*9880d681SAndroid Build Coastguard Worker // so discard it to avoid errors that can be caused by the matcher.
5951*9880d681SAndroid Build Coastguard Worker if (ExtraToken != ".n" && (isThumb() || ExtraToken != ".w")) {
5952*9880d681SAndroid Build Coastguard Worker SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5953*9880d681SAndroid Build Coastguard Worker Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
5954*9880d681SAndroid Build Coastguard Worker }
5955*9880d681SAndroid Build Coastguard Worker }
5956*9880d681SAndroid Build Coastguard Worker
5957*9880d681SAndroid Build Coastguard Worker // Read the remaining operands.
5958*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
5959*9880d681SAndroid Build Coastguard Worker // Read the first operand.
5960*9880d681SAndroid Build Coastguard Worker if (parseOperand(Operands, Mnemonic)) {
5961*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
5962*9880d681SAndroid Build Coastguard Worker return true;
5963*9880d681SAndroid Build Coastguard Worker }
5964*9880d681SAndroid Build Coastguard Worker
5965*9880d681SAndroid Build Coastguard Worker while (getLexer().is(AsmToken::Comma)) {
5966*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the comma.
5967*9880d681SAndroid Build Coastguard Worker
5968*9880d681SAndroid Build Coastguard Worker // Parse and remember the operand.
5969*9880d681SAndroid Build Coastguard Worker if (parseOperand(Operands, Mnemonic)) {
5970*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
5971*9880d681SAndroid Build Coastguard Worker return true;
5972*9880d681SAndroid Build Coastguard Worker }
5973*9880d681SAndroid Build Coastguard Worker }
5974*9880d681SAndroid Build Coastguard Worker }
5975*9880d681SAndroid Build Coastguard Worker
5976*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
5977*9880d681SAndroid Build Coastguard Worker SMLoc Loc = getLexer().getLoc();
5978*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
5979*9880d681SAndroid Build Coastguard Worker return Error(Loc, "unexpected token in argument list");
5980*9880d681SAndroid Build Coastguard Worker }
5981*9880d681SAndroid Build Coastguard Worker
5982*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Consume the EndOfStatement
5983*9880d681SAndroid Build Coastguard Worker
5984*9880d681SAndroid Build Coastguard Worker if (RequireVFPRegisterListCheck) {
5985*9880d681SAndroid Build Coastguard Worker ARMOperand &Op = static_cast<ARMOperand &>(*Operands.back());
5986*9880d681SAndroid Build Coastguard Worker if (AcceptSinglePrecisionOnly && !Op.isSPRRegList())
5987*9880d681SAndroid Build Coastguard Worker return Error(Op.getStartLoc(),
5988*9880d681SAndroid Build Coastguard Worker "VFP/Neon single precision register expected");
5989*9880d681SAndroid Build Coastguard Worker if (AcceptDoublePrecisionOnly && !Op.isDPRRegList())
5990*9880d681SAndroid Build Coastguard Worker return Error(Op.getStartLoc(),
5991*9880d681SAndroid Build Coastguard Worker "VFP/Neon double precision register expected");
5992*9880d681SAndroid Build Coastguard Worker }
5993*9880d681SAndroid Build Coastguard Worker
5994*9880d681SAndroid Build Coastguard Worker tryConvertingToTwoOperandForm(Mnemonic, CarrySetting, Operands);
5995*9880d681SAndroid Build Coastguard Worker
5996*9880d681SAndroid Build Coastguard Worker // Some instructions, mostly Thumb, have forms for the same mnemonic that
5997*9880d681SAndroid Build Coastguard Worker // do and don't have a cc_out optional-def operand. With some spot-checks
5998*9880d681SAndroid Build Coastguard Worker // of the operand list, we can figure out which variant we're trying to
5999*9880d681SAndroid Build Coastguard Worker // parse and adjust accordingly before actually matching. We shouldn't ever
6000*9880d681SAndroid Build Coastguard Worker // try to remove a cc_out operand that was explicitly set on the
6001*9880d681SAndroid Build Coastguard Worker // mnemonic, of course (CarrySetting == true). Reason number #317 the
6002*9880d681SAndroid Build Coastguard Worker // table driven matcher doesn't fit well with the ARM instruction set.
6003*9880d681SAndroid Build Coastguard Worker if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands))
6004*9880d681SAndroid Build Coastguard Worker Operands.erase(Operands.begin() + 1);
6005*9880d681SAndroid Build Coastguard Worker
6006*9880d681SAndroid Build Coastguard Worker // Some instructions have the same mnemonic, but don't always
6007*9880d681SAndroid Build Coastguard Worker // have a predicate. Distinguish them here and delete the
6008*9880d681SAndroid Build Coastguard Worker // predicate if needed.
6009*9880d681SAndroid Build Coastguard Worker if (shouldOmitPredicateOperand(Mnemonic, Operands))
6010*9880d681SAndroid Build Coastguard Worker Operands.erase(Operands.begin() + 1);
6011*9880d681SAndroid Build Coastguard Worker
6012*9880d681SAndroid Build Coastguard Worker // ARM mode 'blx' need special handling, as the register operand version
6013*9880d681SAndroid Build Coastguard Worker // is predicable, but the label operand version is not. So, we can't rely
6014*9880d681SAndroid Build Coastguard Worker // on the Mnemonic based checking to correctly figure out when to put
6015*9880d681SAndroid Build Coastguard Worker // a k_CondCode operand in the list. If we're trying to match the label
6016*9880d681SAndroid Build Coastguard Worker // version, remove the k_CondCode operand here.
6017*9880d681SAndroid Build Coastguard Worker if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
6018*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[2]).isImm())
6019*9880d681SAndroid Build Coastguard Worker Operands.erase(Operands.begin() + 1);
6020*9880d681SAndroid Build Coastguard Worker
6021*9880d681SAndroid Build Coastguard Worker // Adjust operands of ldrexd/strexd to MCK_GPRPair.
6022*9880d681SAndroid Build Coastguard Worker // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
6023*9880d681SAndroid Build Coastguard Worker // a single GPRPair reg operand is used in the .td file to replace the two
6024*9880d681SAndroid Build Coastguard Worker // GPRs. However, when parsing from asm, the two GRPs cannot be automatically
6025*9880d681SAndroid Build Coastguard Worker // expressed as a GPRPair, so we have to manually merge them.
6026*9880d681SAndroid Build Coastguard Worker // FIXME: We would really like to be able to tablegen'erate this.
6027*9880d681SAndroid Build Coastguard Worker if (!isThumb() && Operands.size() > 4 &&
6028*9880d681SAndroid Build Coastguard Worker (Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" ||
6029*9880d681SAndroid Build Coastguard Worker Mnemonic == "stlexd")) {
6030*9880d681SAndroid Build Coastguard Worker bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd");
6031*9880d681SAndroid Build Coastguard Worker unsigned Idx = isLoad ? 2 : 3;
6032*9880d681SAndroid Build Coastguard Worker ARMOperand &Op1 = static_cast<ARMOperand &>(*Operands[Idx]);
6033*9880d681SAndroid Build Coastguard Worker ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[Idx + 1]);
6034*9880d681SAndroid Build Coastguard Worker
6035*9880d681SAndroid Build Coastguard Worker const MCRegisterClass& MRC = MRI->getRegClass(ARM::GPRRegClassID);
6036*9880d681SAndroid Build Coastguard Worker // Adjust only if Op1 and Op2 are GPRs.
6037*9880d681SAndroid Build Coastguard Worker if (Op1.isReg() && Op2.isReg() && MRC.contains(Op1.getReg()) &&
6038*9880d681SAndroid Build Coastguard Worker MRC.contains(Op2.getReg())) {
6039*9880d681SAndroid Build Coastguard Worker unsigned Reg1 = Op1.getReg();
6040*9880d681SAndroid Build Coastguard Worker unsigned Reg2 = Op2.getReg();
6041*9880d681SAndroid Build Coastguard Worker unsigned Rt = MRI->getEncodingValue(Reg1);
6042*9880d681SAndroid Build Coastguard Worker unsigned Rt2 = MRI->getEncodingValue(Reg2);
6043*9880d681SAndroid Build Coastguard Worker
6044*9880d681SAndroid Build Coastguard Worker // Rt2 must be Rt + 1 and Rt must be even.
6045*9880d681SAndroid Build Coastguard Worker if (Rt + 1 != Rt2 || (Rt & 1)) {
6046*9880d681SAndroid Build Coastguard Worker Error(Op2.getStartLoc(), isLoad
6047*9880d681SAndroid Build Coastguard Worker ? "destination operands must be sequential"
6048*9880d681SAndroid Build Coastguard Worker : "source operands must be sequential");
6049*9880d681SAndroid Build Coastguard Worker return true;
6050*9880d681SAndroid Build Coastguard Worker }
6051*9880d681SAndroid Build Coastguard Worker unsigned NewReg = MRI->getMatchingSuperReg(Reg1, ARM::gsub_0,
6052*9880d681SAndroid Build Coastguard Worker &(MRI->getRegClass(ARM::GPRPairRegClassID)));
6053*9880d681SAndroid Build Coastguard Worker Operands[Idx] =
6054*9880d681SAndroid Build Coastguard Worker ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc());
6055*9880d681SAndroid Build Coastguard Worker Operands.erase(Operands.begin() + Idx + 1);
6056*9880d681SAndroid Build Coastguard Worker }
6057*9880d681SAndroid Build Coastguard Worker }
6058*9880d681SAndroid Build Coastguard Worker
6059*9880d681SAndroid Build Coastguard Worker // GNU Assembler extension (compatibility)
6060*9880d681SAndroid Build Coastguard Worker if ((Mnemonic == "ldrd" || Mnemonic == "strd")) {
6061*9880d681SAndroid Build Coastguard Worker ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]);
6062*9880d681SAndroid Build Coastguard Worker ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
6063*9880d681SAndroid Build Coastguard Worker if (Op3.isMem()) {
6064*9880d681SAndroid Build Coastguard Worker assert(Op2.isReg() && "expected register argument");
6065*9880d681SAndroid Build Coastguard Worker
6066*9880d681SAndroid Build Coastguard Worker unsigned SuperReg = MRI->getMatchingSuperReg(
6067*9880d681SAndroid Build Coastguard Worker Op2.getReg(), ARM::gsub_0, &MRI->getRegClass(ARM::GPRPairRegClassID));
6068*9880d681SAndroid Build Coastguard Worker
6069*9880d681SAndroid Build Coastguard Worker assert(SuperReg && "expected register pair");
6070*9880d681SAndroid Build Coastguard Worker
6071*9880d681SAndroid Build Coastguard Worker unsigned PairedReg = MRI->getSubReg(SuperReg, ARM::gsub_1);
6072*9880d681SAndroid Build Coastguard Worker
6073*9880d681SAndroid Build Coastguard Worker Operands.insert(
6074*9880d681SAndroid Build Coastguard Worker Operands.begin() + 3,
6075*9880d681SAndroid Build Coastguard Worker ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc()));
6076*9880d681SAndroid Build Coastguard Worker }
6077*9880d681SAndroid Build Coastguard Worker }
6078*9880d681SAndroid Build Coastguard Worker
6079*9880d681SAndroid Build Coastguard Worker // FIXME: As said above, this is all a pretty gross hack. This instruction
6080*9880d681SAndroid Build Coastguard Worker // does not fit with other "subs" and tblgen.
6081*9880d681SAndroid Build Coastguard Worker // Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction
6082*9880d681SAndroid Build Coastguard Worker // so the Mnemonic is the original name "subs" and delete the predicate
6083*9880d681SAndroid Build Coastguard Worker // operand so it will match the table entry.
6084*9880d681SAndroid Build Coastguard Worker if (isThumbTwo() && Mnemonic == "sub" && Operands.size() == 6 &&
6085*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).isReg() &&
6086*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).getReg() == ARM::PC &&
6087*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).isReg() &&
6088*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[4]).getReg() == ARM::LR &&
6089*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[5]).isImm()) {
6090*9880d681SAndroid Build Coastguard Worker Operands.front() = ARMOperand::CreateToken(Name, NameLoc);
6091*9880d681SAndroid Build Coastguard Worker Operands.erase(Operands.begin() + 1);
6092*9880d681SAndroid Build Coastguard Worker }
6093*9880d681SAndroid Build Coastguard Worker return false;
6094*9880d681SAndroid Build Coastguard Worker }
6095*9880d681SAndroid Build Coastguard Worker
6096*9880d681SAndroid Build Coastguard Worker // Validate context-sensitive operand constraints.
6097*9880d681SAndroid Build Coastguard Worker
6098*9880d681SAndroid Build Coastguard Worker // return 'true' if register list contains non-low GPR registers,
6099*9880d681SAndroid Build Coastguard Worker // 'false' otherwise. If Reg is in the register list or is HiReg, set
6100*9880d681SAndroid Build Coastguard Worker // 'containsReg' to true.
checkLowRegisterList(const MCInst & Inst,unsigned OpNo,unsigned Reg,unsigned HiReg,bool & containsReg)6101*9880d681SAndroid Build Coastguard Worker static bool checkLowRegisterList(const MCInst &Inst, unsigned OpNo,
6102*9880d681SAndroid Build Coastguard Worker unsigned Reg, unsigned HiReg,
6103*9880d681SAndroid Build Coastguard Worker bool &containsReg) {
6104*9880d681SAndroid Build Coastguard Worker containsReg = false;
6105*9880d681SAndroid Build Coastguard Worker for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
6106*9880d681SAndroid Build Coastguard Worker unsigned OpReg = Inst.getOperand(i).getReg();
6107*9880d681SAndroid Build Coastguard Worker if (OpReg == Reg)
6108*9880d681SAndroid Build Coastguard Worker containsReg = true;
6109*9880d681SAndroid Build Coastguard Worker // Anything other than a low register isn't legal here.
6110*9880d681SAndroid Build Coastguard Worker if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
6111*9880d681SAndroid Build Coastguard Worker return true;
6112*9880d681SAndroid Build Coastguard Worker }
6113*9880d681SAndroid Build Coastguard Worker return false;
6114*9880d681SAndroid Build Coastguard Worker }
6115*9880d681SAndroid Build Coastguard Worker
6116*9880d681SAndroid Build Coastguard Worker // Check if the specified regisgter is in the register list of the inst,
6117*9880d681SAndroid Build Coastguard Worker // starting at the indicated operand number.
listContainsReg(const MCInst & Inst,unsigned OpNo,unsigned Reg)6118*9880d681SAndroid Build Coastguard Worker static bool listContainsReg(const MCInst &Inst, unsigned OpNo, unsigned Reg) {
6119*9880d681SAndroid Build Coastguard Worker for (unsigned i = OpNo, e = Inst.getNumOperands(); i < e; ++i) {
6120*9880d681SAndroid Build Coastguard Worker unsigned OpReg = Inst.getOperand(i).getReg();
6121*9880d681SAndroid Build Coastguard Worker if (OpReg == Reg)
6122*9880d681SAndroid Build Coastguard Worker return true;
6123*9880d681SAndroid Build Coastguard Worker }
6124*9880d681SAndroid Build Coastguard Worker return false;
6125*9880d681SAndroid Build Coastguard Worker }
6126*9880d681SAndroid Build Coastguard Worker
6127*9880d681SAndroid Build Coastguard Worker // Return true if instruction has the interesting property of being
6128*9880d681SAndroid Build Coastguard Worker // allowed in IT blocks, but not being predicable.
instIsBreakpoint(const MCInst & Inst)6129*9880d681SAndroid Build Coastguard Worker static bool instIsBreakpoint(const MCInst &Inst) {
6130*9880d681SAndroid Build Coastguard Worker return Inst.getOpcode() == ARM::tBKPT ||
6131*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() == ARM::BKPT ||
6132*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() == ARM::tHLT ||
6133*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() == ARM::HLT;
6134*9880d681SAndroid Build Coastguard Worker
6135*9880d681SAndroid Build Coastguard Worker }
6136*9880d681SAndroid Build Coastguard Worker
validatetLDMRegList(const MCInst & Inst,const OperandVector & Operands,unsigned ListNo,bool IsARPop)6137*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::validatetLDMRegList(const MCInst &Inst,
6138*9880d681SAndroid Build Coastguard Worker const OperandVector &Operands,
6139*9880d681SAndroid Build Coastguard Worker unsigned ListNo, bool IsARPop) {
6140*9880d681SAndroid Build Coastguard Worker const ARMOperand &Op = static_cast<const ARMOperand &>(*Operands[ListNo]);
6141*9880d681SAndroid Build Coastguard Worker bool HasWritebackToken = Op.isToken() && Op.getToken() == "!";
6142*9880d681SAndroid Build Coastguard Worker
6143*9880d681SAndroid Build Coastguard Worker bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP);
6144*9880d681SAndroid Build Coastguard Worker bool ListContainsLR = listContainsReg(Inst, ListNo, ARM::LR);
6145*9880d681SAndroid Build Coastguard Worker bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC);
6146*9880d681SAndroid Build Coastguard Worker
6147*9880d681SAndroid Build Coastguard Worker if (!IsARPop && ListContainsSP)
6148*9880d681SAndroid Build Coastguard Worker return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
6149*9880d681SAndroid Build Coastguard Worker "SP may not be in the register list");
6150*9880d681SAndroid Build Coastguard Worker else if (ListContainsPC && ListContainsLR)
6151*9880d681SAndroid Build Coastguard Worker return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
6152*9880d681SAndroid Build Coastguard Worker "PC and LR may not be in the register list simultaneously");
6153*9880d681SAndroid Build Coastguard Worker else if (inITBlock() && !lastInITBlock() && ListContainsPC)
6154*9880d681SAndroid Build Coastguard Worker return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
6155*9880d681SAndroid Build Coastguard Worker "instruction must be outside of IT block or the last "
6156*9880d681SAndroid Build Coastguard Worker "instruction in an IT block");
6157*9880d681SAndroid Build Coastguard Worker return false;
6158*9880d681SAndroid Build Coastguard Worker }
6159*9880d681SAndroid Build Coastguard Worker
validatetSTMRegList(const MCInst & Inst,const OperandVector & Operands,unsigned ListNo)6160*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::validatetSTMRegList(const MCInst &Inst,
6161*9880d681SAndroid Build Coastguard Worker const OperandVector &Operands,
6162*9880d681SAndroid Build Coastguard Worker unsigned ListNo) {
6163*9880d681SAndroid Build Coastguard Worker const ARMOperand &Op = static_cast<const ARMOperand &>(*Operands[ListNo]);
6164*9880d681SAndroid Build Coastguard Worker bool HasWritebackToken = Op.isToken() && Op.getToken() == "!";
6165*9880d681SAndroid Build Coastguard Worker
6166*9880d681SAndroid Build Coastguard Worker bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP);
6167*9880d681SAndroid Build Coastguard Worker bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC);
6168*9880d681SAndroid Build Coastguard Worker
6169*9880d681SAndroid Build Coastguard Worker if (ListContainsSP && ListContainsPC)
6170*9880d681SAndroid Build Coastguard Worker return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
6171*9880d681SAndroid Build Coastguard Worker "SP and PC may not be in the register list");
6172*9880d681SAndroid Build Coastguard Worker else if (ListContainsSP)
6173*9880d681SAndroid Build Coastguard Worker return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
6174*9880d681SAndroid Build Coastguard Worker "SP may not be in the register list");
6175*9880d681SAndroid Build Coastguard Worker else if (ListContainsPC)
6176*9880d681SAndroid Build Coastguard Worker return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
6177*9880d681SAndroid Build Coastguard Worker "PC may not be in the register list");
6178*9880d681SAndroid Build Coastguard Worker return false;
6179*9880d681SAndroid Build Coastguard Worker }
6180*9880d681SAndroid Build Coastguard Worker
6181*9880d681SAndroid Build Coastguard Worker // FIXME: We would really like to be able to tablegen'erate this.
validateInstruction(MCInst & Inst,const OperandVector & Operands)6182*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::validateInstruction(MCInst &Inst,
6183*9880d681SAndroid Build Coastguard Worker const OperandVector &Operands) {
6184*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
6185*9880d681SAndroid Build Coastguard Worker SMLoc Loc = Operands[0]->getStartLoc();
6186*9880d681SAndroid Build Coastguard Worker
6187*9880d681SAndroid Build Coastguard Worker // Check the IT block state first.
6188*9880d681SAndroid Build Coastguard Worker // NOTE: BKPT and HLT instructions have the interesting property of being
6189*9880d681SAndroid Build Coastguard Worker // allowed in IT blocks, but not being predicable. They just always execute.
6190*9880d681SAndroid Build Coastguard Worker if (inITBlock() && !instIsBreakpoint(Inst)) {
6191*9880d681SAndroid Build Coastguard Worker unsigned Bit = 1;
6192*9880d681SAndroid Build Coastguard Worker if (ITState.FirstCond)
6193*9880d681SAndroid Build Coastguard Worker ITState.FirstCond = false;
6194*9880d681SAndroid Build Coastguard Worker else
6195*9880d681SAndroid Build Coastguard Worker Bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
6196*9880d681SAndroid Build Coastguard Worker // The instruction must be predicable.
6197*9880d681SAndroid Build Coastguard Worker if (!MCID.isPredicable())
6198*9880d681SAndroid Build Coastguard Worker return Error(Loc, "instructions in IT block must be predicable");
6199*9880d681SAndroid Build Coastguard Worker unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
6200*9880d681SAndroid Build Coastguard Worker unsigned ITCond = Bit ? ITState.Cond :
6201*9880d681SAndroid Build Coastguard Worker ARMCC::getOppositeCondition(ITState.Cond);
6202*9880d681SAndroid Build Coastguard Worker if (Cond != ITCond) {
6203*9880d681SAndroid Build Coastguard Worker // Find the condition code Operand to get its SMLoc information.
6204*9880d681SAndroid Build Coastguard Worker SMLoc CondLoc;
6205*9880d681SAndroid Build Coastguard Worker for (unsigned I = 1; I < Operands.size(); ++I)
6206*9880d681SAndroid Build Coastguard Worker if (static_cast<ARMOperand &>(*Operands[I]).isCondCode())
6207*9880d681SAndroid Build Coastguard Worker CondLoc = Operands[I]->getStartLoc();
6208*9880d681SAndroid Build Coastguard Worker return Error(CondLoc, "incorrect condition in IT block; got '" +
6209*9880d681SAndroid Build Coastguard Worker StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
6210*9880d681SAndroid Build Coastguard Worker "', but expected '" +
6211*9880d681SAndroid Build Coastguard Worker ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
6212*9880d681SAndroid Build Coastguard Worker }
6213*9880d681SAndroid Build Coastguard Worker // Check for non-'al' condition codes outside of the IT block.
6214*9880d681SAndroid Build Coastguard Worker } else if (isThumbTwo() && MCID.isPredicable() &&
6215*9880d681SAndroid Build Coastguard Worker Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
6216*9880d681SAndroid Build Coastguard Worker ARMCC::AL && Inst.getOpcode() != ARM::tBcc &&
6217*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() != ARM::t2Bcc)
6218*9880d681SAndroid Build Coastguard Worker return Error(Loc, "predicated instructions must be in IT block");
6219*9880d681SAndroid Build Coastguard Worker
6220*9880d681SAndroid Build Coastguard Worker const unsigned Opcode = Inst.getOpcode();
6221*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
6222*9880d681SAndroid Build Coastguard Worker case ARM::LDRD:
6223*9880d681SAndroid Build Coastguard Worker case ARM::LDRD_PRE:
6224*9880d681SAndroid Build Coastguard Worker case ARM::LDRD_POST: {
6225*9880d681SAndroid Build Coastguard Worker const unsigned RtReg = Inst.getOperand(0).getReg();
6226*9880d681SAndroid Build Coastguard Worker
6227*9880d681SAndroid Build Coastguard Worker // Rt can't be R14.
6228*9880d681SAndroid Build Coastguard Worker if (RtReg == ARM::LR)
6229*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6230*9880d681SAndroid Build Coastguard Worker "Rt can't be R14");
6231*9880d681SAndroid Build Coastguard Worker
6232*9880d681SAndroid Build Coastguard Worker const unsigned Rt = MRI->getEncodingValue(RtReg);
6233*9880d681SAndroid Build Coastguard Worker // Rt must be even-numbered.
6234*9880d681SAndroid Build Coastguard Worker if ((Rt & 1) == 1)
6235*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6236*9880d681SAndroid Build Coastguard Worker "Rt must be even-numbered");
6237*9880d681SAndroid Build Coastguard Worker
6238*9880d681SAndroid Build Coastguard Worker // Rt2 must be Rt + 1.
6239*9880d681SAndroid Build Coastguard Worker const unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
6240*9880d681SAndroid Build Coastguard Worker if (Rt2 != Rt + 1)
6241*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6242*9880d681SAndroid Build Coastguard Worker "destination operands must be sequential");
6243*9880d681SAndroid Build Coastguard Worker
6244*9880d681SAndroid Build Coastguard Worker if (Opcode == ARM::LDRD_PRE || Opcode == ARM::LDRD_POST) {
6245*9880d681SAndroid Build Coastguard Worker const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg());
6246*9880d681SAndroid Build Coastguard Worker // For addressing modes with writeback, the base register needs to be
6247*9880d681SAndroid Build Coastguard Worker // different from the destination registers.
6248*9880d681SAndroid Build Coastguard Worker if (Rn == Rt || Rn == Rt2)
6249*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6250*9880d681SAndroid Build Coastguard Worker "base register needs to be different from destination "
6251*9880d681SAndroid Build Coastguard Worker "registers");
6252*9880d681SAndroid Build Coastguard Worker }
6253*9880d681SAndroid Build Coastguard Worker
6254*9880d681SAndroid Build Coastguard Worker return false;
6255*9880d681SAndroid Build Coastguard Worker }
6256*9880d681SAndroid Build Coastguard Worker case ARM::t2LDRDi8:
6257*9880d681SAndroid Build Coastguard Worker case ARM::t2LDRD_PRE:
6258*9880d681SAndroid Build Coastguard Worker case ARM::t2LDRD_POST: {
6259*9880d681SAndroid Build Coastguard Worker // Rt2 must be different from Rt.
6260*9880d681SAndroid Build Coastguard Worker unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
6261*9880d681SAndroid Build Coastguard Worker unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
6262*9880d681SAndroid Build Coastguard Worker if (Rt2 == Rt)
6263*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6264*9880d681SAndroid Build Coastguard Worker "destination operands can't be identical");
6265*9880d681SAndroid Build Coastguard Worker return false;
6266*9880d681SAndroid Build Coastguard Worker }
6267*9880d681SAndroid Build Coastguard Worker case ARM::t2BXJ: {
6268*9880d681SAndroid Build Coastguard Worker const unsigned RmReg = Inst.getOperand(0).getReg();
6269*9880d681SAndroid Build Coastguard Worker // Rm = SP is no longer unpredictable in v8-A
6270*9880d681SAndroid Build Coastguard Worker if (RmReg == ARM::SP && !hasV8Ops())
6271*9880d681SAndroid Build Coastguard Worker return Error(Operands[2]->getStartLoc(),
6272*9880d681SAndroid Build Coastguard Worker "r13 (SP) is an unpredictable operand to BXJ");
6273*9880d681SAndroid Build Coastguard Worker return false;
6274*9880d681SAndroid Build Coastguard Worker }
6275*9880d681SAndroid Build Coastguard Worker case ARM::STRD: {
6276*9880d681SAndroid Build Coastguard Worker // Rt2 must be Rt + 1.
6277*9880d681SAndroid Build Coastguard Worker unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
6278*9880d681SAndroid Build Coastguard Worker unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
6279*9880d681SAndroid Build Coastguard Worker if (Rt2 != Rt + 1)
6280*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6281*9880d681SAndroid Build Coastguard Worker "source operands must be sequential");
6282*9880d681SAndroid Build Coastguard Worker return false;
6283*9880d681SAndroid Build Coastguard Worker }
6284*9880d681SAndroid Build Coastguard Worker case ARM::STRD_PRE:
6285*9880d681SAndroid Build Coastguard Worker case ARM::STRD_POST: {
6286*9880d681SAndroid Build Coastguard Worker // Rt2 must be Rt + 1.
6287*9880d681SAndroid Build Coastguard Worker unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg());
6288*9880d681SAndroid Build Coastguard Worker unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(2).getReg());
6289*9880d681SAndroid Build Coastguard Worker if (Rt2 != Rt + 1)
6290*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6291*9880d681SAndroid Build Coastguard Worker "source operands must be sequential");
6292*9880d681SAndroid Build Coastguard Worker return false;
6293*9880d681SAndroid Build Coastguard Worker }
6294*9880d681SAndroid Build Coastguard Worker case ARM::STR_PRE_IMM:
6295*9880d681SAndroid Build Coastguard Worker case ARM::STR_PRE_REG:
6296*9880d681SAndroid Build Coastguard Worker case ARM::STR_POST_IMM:
6297*9880d681SAndroid Build Coastguard Worker case ARM::STR_POST_REG:
6298*9880d681SAndroid Build Coastguard Worker case ARM::STRH_PRE:
6299*9880d681SAndroid Build Coastguard Worker case ARM::STRH_POST:
6300*9880d681SAndroid Build Coastguard Worker case ARM::STRB_PRE_IMM:
6301*9880d681SAndroid Build Coastguard Worker case ARM::STRB_PRE_REG:
6302*9880d681SAndroid Build Coastguard Worker case ARM::STRB_POST_IMM:
6303*9880d681SAndroid Build Coastguard Worker case ARM::STRB_POST_REG: {
6304*9880d681SAndroid Build Coastguard Worker // Rt must be different from Rn.
6305*9880d681SAndroid Build Coastguard Worker const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg());
6306*9880d681SAndroid Build Coastguard Worker const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg());
6307*9880d681SAndroid Build Coastguard Worker
6308*9880d681SAndroid Build Coastguard Worker if (Rt == Rn)
6309*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6310*9880d681SAndroid Build Coastguard Worker "source register and base register can't be identical");
6311*9880d681SAndroid Build Coastguard Worker return false;
6312*9880d681SAndroid Build Coastguard Worker }
6313*9880d681SAndroid Build Coastguard Worker case ARM::LDR_PRE_IMM:
6314*9880d681SAndroid Build Coastguard Worker case ARM::LDR_PRE_REG:
6315*9880d681SAndroid Build Coastguard Worker case ARM::LDR_POST_IMM:
6316*9880d681SAndroid Build Coastguard Worker case ARM::LDR_POST_REG:
6317*9880d681SAndroid Build Coastguard Worker case ARM::LDRH_PRE:
6318*9880d681SAndroid Build Coastguard Worker case ARM::LDRH_POST:
6319*9880d681SAndroid Build Coastguard Worker case ARM::LDRSH_PRE:
6320*9880d681SAndroid Build Coastguard Worker case ARM::LDRSH_POST:
6321*9880d681SAndroid Build Coastguard Worker case ARM::LDRB_PRE_IMM:
6322*9880d681SAndroid Build Coastguard Worker case ARM::LDRB_PRE_REG:
6323*9880d681SAndroid Build Coastguard Worker case ARM::LDRB_POST_IMM:
6324*9880d681SAndroid Build Coastguard Worker case ARM::LDRB_POST_REG:
6325*9880d681SAndroid Build Coastguard Worker case ARM::LDRSB_PRE:
6326*9880d681SAndroid Build Coastguard Worker case ARM::LDRSB_POST: {
6327*9880d681SAndroid Build Coastguard Worker // Rt must be different from Rn.
6328*9880d681SAndroid Build Coastguard Worker const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
6329*9880d681SAndroid Build Coastguard Worker const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg());
6330*9880d681SAndroid Build Coastguard Worker
6331*9880d681SAndroid Build Coastguard Worker if (Rt == Rn)
6332*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6333*9880d681SAndroid Build Coastguard Worker "destination register and base register can't be identical");
6334*9880d681SAndroid Build Coastguard Worker return false;
6335*9880d681SAndroid Build Coastguard Worker }
6336*9880d681SAndroid Build Coastguard Worker case ARM::SBFX:
6337*9880d681SAndroid Build Coastguard Worker case ARM::UBFX: {
6338*9880d681SAndroid Build Coastguard Worker // Width must be in range [1, 32-lsb].
6339*9880d681SAndroid Build Coastguard Worker unsigned LSB = Inst.getOperand(2).getImm();
6340*9880d681SAndroid Build Coastguard Worker unsigned Widthm1 = Inst.getOperand(3).getImm();
6341*9880d681SAndroid Build Coastguard Worker if (Widthm1 >= 32 - LSB)
6342*9880d681SAndroid Build Coastguard Worker return Error(Operands[5]->getStartLoc(),
6343*9880d681SAndroid Build Coastguard Worker "bitfield width must be in range [1,32-lsb]");
6344*9880d681SAndroid Build Coastguard Worker return false;
6345*9880d681SAndroid Build Coastguard Worker }
6346*9880d681SAndroid Build Coastguard Worker // Notionally handles ARM::tLDMIA_UPD too.
6347*9880d681SAndroid Build Coastguard Worker case ARM::tLDMIA: {
6348*9880d681SAndroid Build Coastguard Worker // If we're parsing Thumb2, the .w variant is available and handles
6349*9880d681SAndroid Build Coastguard Worker // most cases that are normally illegal for a Thumb1 LDM instruction.
6350*9880d681SAndroid Build Coastguard Worker // We'll make the transformation in processInstruction() if necessary.
6351*9880d681SAndroid Build Coastguard Worker //
6352*9880d681SAndroid Build Coastguard Worker // Thumb LDM instructions are writeback iff the base register is not
6353*9880d681SAndroid Build Coastguard Worker // in the register list.
6354*9880d681SAndroid Build Coastguard Worker unsigned Rn = Inst.getOperand(0).getReg();
6355*9880d681SAndroid Build Coastguard Worker bool HasWritebackToken =
6356*9880d681SAndroid Build Coastguard Worker (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
6357*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).getToken() == "!");
6358*9880d681SAndroid Build Coastguard Worker bool ListContainsBase;
6359*9880d681SAndroid Build Coastguard Worker if (checkLowRegisterList(Inst, 3, Rn, 0, ListContainsBase) && !isThumbTwo())
6360*9880d681SAndroid Build Coastguard Worker return Error(Operands[3 + HasWritebackToken]->getStartLoc(),
6361*9880d681SAndroid Build Coastguard Worker "registers must be in range r0-r7");
6362*9880d681SAndroid Build Coastguard Worker // If we should have writeback, then there should be a '!' token.
6363*9880d681SAndroid Build Coastguard Worker if (!ListContainsBase && !HasWritebackToken && !isThumbTwo())
6364*9880d681SAndroid Build Coastguard Worker return Error(Operands[2]->getStartLoc(),
6365*9880d681SAndroid Build Coastguard Worker "writeback operator '!' expected");
6366*9880d681SAndroid Build Coastguard Worker // If we should not have writeback, there must not be a '!'. This is
6367*9880d681SAndroid Build Coastguard Worker // true even for the 32-bit wide encodings.
6368*9880d681SAndroid Build Coastguard Worker if (ListContainsBase && HasWritebackToken)
6369*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6370*9880d681SAndroid Build Coastguard Worker "writeback operator '!' not allowed when base register "
6371*9880d681SAndroid Build Coastguard Worker "in register list");
6372*9880d681SAndroid Build Coastguard Worker
6373*9880d681SAndroid Build Coastguard Worker if (validatetLDMRegList(Inst, Operands, 3))
6374*9880d681SAndroid Build Coastguard Worker return true;
6375*9880d681SAndroid Build Coastguard Worker break;
6376*9880d681SAndroid Build Coastguard Worker }
6377*9880d681SAndroid Build Coastguard Worker case ARM::LDMIA_UPD:
6378*9880d681SAndroid Build Coastguard Worker case ARM::LDMDB_UPD:
6379*9880d681SAndroid Build Coastguard Worker case ARM::LDMIB_UPD:
6380*9880d681SAndroid Build Coastguard Worker case ARM::LDMDA_UPD:
6381*9880d681SAndroid Build Coastguard Worker // ARM variants loading and updating the same register are only officially
6382*9880d681SAndroid Build Coastguard Worker // UNPREDICTABLE on v7 upwards. Goodness knows what they did before.
6383*9880d681SAndroid Build Coastguard Worker if (!hasV7Ops())
6384*9880d681SAndroid Build Coastguard Worker break;
6385*9880d681SAndroid Build Coastguard Worker if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
6386*9880d681SAndroid Build Coastguard Worker return Error(Operands.back()->getStartLoc(),
6387*9880d681SAndroid Build Coastguard Worker "writeback register not allowed in register list");
6388*9880d681SAndroid Build Coastguard Worker break;
6389*9880d681SAndroid Build Coastguard Worker case ARM::t2LDMIA:
6390*9880d681SAndroid Build Coastguard Worker case ARM::t2LDMDB:
6391*9880d681SAndroid Build Coastguard Worker if (validatetLDMRegList(Inst, Operands, 3))
6392*9880d681SAndroid Build Coastguard Worker return true;
6393*9880d681SAndroid Build Coastguard Worker break;
6394*9880d681SAndroid Build Coastguard Worker case ARM::t2STMIA:
6395*9880d681SAndroid Build Coastguard Worker case ARM::t2STMDB:
6396*9880d681SAndroid Build Coastguard Worker if (validatetSTMRegList(Inst, Operands, 3))
6397*9880d681SAndroid Build Coastguard Worker return true;
6398*9880d681SAndroid Build Coastguard Worker break;
6399*9880d681SAndroid Build Coastguard Worker case ARM::t2LDMIA_UPD:
6400*9880d681SAndroid Build Coastguard Worker case ARM::t2LDMDB_UPD:
6401*9880d681SAndroid Build Coastguard Worker case ARM::t2STMIA_UPD:
6402*9880d681SAndroid Build Coastguard Worker case ARM::t2STMDB_UPD: {
6403*9880d681SAndroid Build Coastguard Worker if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
6404*9880d681SAndroid Build Coastguard Worker return Error(Operands.back()->getStartLoc(),
6405*9880d681SAndroid Build Coastguard Worker "writeback register not allowed in register list");
6406*9880d681SAndroid Build Coastguard Worker
6407*9880d681SAndroid Build Coastguard Worker if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
6408*9880d681SAndroid Build Coastguard Worker if (validatetLDMRegList(Inst, Operands, 3))
6409*9880d681SAndroid Build Coastguard Worker return true;
6410*9880d681SAndroid Build Coastguard Worker } else {
6411*9880d681SAndroid Build Coastguard Worker if (validatetSTMRegList(Inst, Operands, 3))
6412*9880d681SAndroid Build Coastguard Worker return true;
6413*9880d681SAndroid Build Coastguard Worker }
6414*9880d681SAndroid Build Coastguard Worker break;
6415*9880d681SAndroid Build Coastguard Worker }
6416*9880d681SAndroid Build Coastguard Worker case ARM::sysLDMIA_UPD:
6417*9880d681SAndroid Build Coastguard Worker case ARM::sysLDMDA_UPD:
6418*9880d681SAndroid Build Coastguard Worker case ARM::sysLDMDB_UPD:
6419*9880d681SAndroid Build Coastguard Worker case ARM::sysLDMIB_UPD:
6420*9880d681SAndroid Build Coastguard Worker if (!listContainsReg(Inst, 3, ARM::PC))
6421*9880d681SAndroid Build Coastguard Worker return Error(Operands[4]->getStartLoc(),
6422*9880d681SAndroid Build Coastguard Worker "writeback register only allowed on system LDM "
6423*9880d681SAndroid Build Coastguard Worker "if PC in register-list");
6424*9880d681SAndroid Build Coastguard Worker break;
6425*9880d681SAndroid Build Coastguard Worker case ARM::sysSTMIA_UPD:
6426*9880d681SAndroid Build Coastguard Worker case ARM::sysSTMDA_UPD:
6427*9880d681SAndroid Build Coastguard Worker case ARM::sysSTMDB_UPD:
6428*9880d681SAndroid Build Coastguard Worker case ARM::sysSTMIB_UPD:
6429*9880d681SAndroid Build Coastguard Worker return Error(Operands[2]->getStartLoc(),
6430*9880d681SAndroid Build Coastguard Worker "system STM cannot have writeback register");
6431*9880d681SAndroid Build Coastguard Worker case ARM::tMUL: {
6432*9880d681SAndroid Build Coastguard Worker // The second source operand must be the same register as the destination
6433*9880d681SAndroid Build Coastguard Worker // operand.
6434*9880d681SAndroid Build Coastguard Worker //
6435*9880d681SAndroid Build Coastguard Worker // In this case, we must directly check the parsed operands because the
6436*9880d681SAndroid Build Coastguard Worker // cvtThumbMultiply() function is written in such a way that it guarantees
6437*9880d681SAndroid Build Coastguard Worker // this first statement is always true for the new Inst. Essentially, the
6438*9880d681SAndroid Build Coastguard Worker // destination is unconditionally copied into the second source operand
6439*9880d681SAndroid Build Coastguard Worker // without checking to see if it matches what we actually parsed.
6440*9880d681SAndroid Build Coastguard Worker if (Operands.size() == 6 && (((ARMOperand &)*Operands[3]).getReg() !=
6441*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[5]).getReg()) &&
6442*9880d681SAndroid Build Coastguard Worker (((ARMOperand &)*Operands[3]).getReg() !=
6443*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[4]).getReg())) {
6444*9880d681SAndroid Build Coastguard Worker return Error(Operands[3]->getStartLoc(),
6445*9880d681SAndroid Build Coastguard Worker "destination register must match source register");
6446*9880d681SAndroid Build Coastguard Worker }
6447*9880d681SAndroid Build Coastguard Worker break;
6448*9880d681SAndroid Build Coastguard Worker }
6449*9880d681SAndroid Build Coastguard Worker // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
6450*9880d681SAndroid Build Coastguard Worker // so only issue a diagnostic for thumb1. The instructions will be
6451*9880d681SAndroid Build Coastguard Worker // switched to the t2 encodings in processInstruction() if necessary.
6452*9880d681SAndroid Build Coastguard Worker case ARM::tPOP: {
6453*9880d681SAndroid Build Coastguard Worker bool ListContainsBase;
6454*9880d681SAndroid Build Coastguard Worker if (checkLowRegisterList(Inst, 2, 0, ARM::PC, ListContainsBase) &&
6455*9880d681SAndroid Build Coastguard Worker !isThumbTwo())
6456*9880d681SAndroid Build Coastguard Worker return Error(Operands[2]->getStartLoc(),
6457*9880d681SAndroid Build Coastguard Worker "registers must be in range r0-r7 or pc");
6458*9880d681SAndroid Build Coastguard Worker if (validatetLDMRegList(Inst, Operands, 2, !isMClass()))
6459*9880d681SAndroid Build Coastguard Worker return true;
6460*9880d681SAndroid Build Coastguard Worker break;
6461*9880d681SAndroid Build Coastguard Worker }
6462*9880d681SAndroid Build Coastguard Worker case ARM::tPUSH: {
6463*9880d681SAndroid Build Coastguard Worker bool ListContainsBase;
6464*9880d681SAndroid Build Coastguard Worker if (checkLowRegisterList(Inst, 2, 0, ARM::LR, ListContainsBase) &&
6465*9880d681SAndroid Build Coastguard Worker !isThumbTwo())
6466*9880d681SAndroid Build Coastguard Worker return Error(Operands[2]->getStartLoc(),
6467*9880d681SAndroid Build Coastguard Worker "registers must be in range r0-r7 or lr");
6468*9880d681SAndroid Build Coastguard Worker if (validatetSTMRegList(Inst, Operands, 2))
6469*9880d681SAndroid Build Coastguard Worker return true;
6470*9880d681SAndroid Build Coastguard Worker break;
6471*9880d681SAndroid Build Coastguard Worker }
6472*9880d681SAndroid Build Coastguard Worker case ARM::tSTMIA_UPD: {
6473*9880d681SAndroid Build Coastguard Worker bool ListContainsBase, InvalidLowList;
6474*9880d681SAndroid Build Coastguard Worker InvalidLowList = checkLowRegisterList(Inst, 4, Inst.getOperand(0).getReg(),
6475*9880d681SAndroid Build Coastguard Worker 0, ListContainsBase);
6476*9880d681SAndroid Build Coastguard Worker if (InvalidLowList && !isThumbTwo())
6477*9880d681SAndroid Build Coastguard Worker return Error(Operands[4]->getStartLoc(),
6478*9880d681SAndroid Build Coastguard Worker "registers must be in range r0-r7");
6479*9880d681SAndroid Build Coastguard Worker
6480*9880d681SAndroid Build Coastguard Worker // This would be converted to a 32-bit stm, but that's not valid if the
6481*9880d681SAndroid Build Coastguard Worker // writeback register is in the list.
6482*9880d681SAndroid Build Coastguard Worker if (InvalidLowList && ListContainsBase)
6483*9880d681SAndroid Build Coastguard Worker return Error(Operands[4]->getStartLoc(),
6484*9880d681SAndroid Build Coastguard Worker "writeback operator '!' not allowed when base register "
6485*9880d681SAndroid Build Coastguard Worker "in register list");
6486*9880d681SAndroid Build Coastguard Worker
6487*9880d681SAndroid Build Coastguard Worker if (validatetSTMRegList(Inst, Operands, 4))
6488*9880d681SAndroid Build Coastguard Worker return true;
6489*9880d681SAndroid Build Coastguard Worker break;
6490*9880d681SAndroid Build Coastguard Worker }
6491*9880d681SAndroid Build Coastguard Worker case ARM::tADDrSP: {
6492*9880d681SAndroid Build Coastguard Worker // If the non-SP source operand and the destination operand are not the
6493*9880d681SAndroid Build Coastguard Worker // same, we need thumb2 (for the wide encoding), or we have an error.
6494*9880d681SAndroid Build Coastguard Worker if (!isThumbTwo() &&
6495*9880d681SAndroid Build Coastguard Worker Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
6496*9880d681SAndroid Build Coastguard Worker return Error(Operands[4]->getStartLoc(),
6497*9880d681SAndroid Build Coastguard Worker "source register must be the same as destination");
6498*9880d681SAndroid Build Coastguard Worker }
6499*9880d681SAndroid Build Coastguard Worker break;
6500*9880d681SAndroid Build Coastguard Worker }
6501*9880d681SAndroid Build Coastguard Worker // Final range checking for Thumb unconditional branch instructions.
6502*9880d681SAndroid Build Coastguard Worker case ARM::tB:
6503*9880d681SAndroid Build Coastguard Worker if (!(static_cast<ARMOperand &>(*Operands[2])).isSignedOffset<11, 1>())
6504*9880d681SAndroid Build Coastguard Worker return Error(Operands[2]->getStartLoc(), "branch target out of range");
6505*9880d681SAndroid Build Coastguard Worker break;
6506*9880d681SAndroid Build Coastguard Worker case ARM::t2B: {
6507*9880d681SAndroid Build Coastguard Worker int op = (Operands[2]->isImm()) ? 2 : 3;
6508*9880d681SAndroid Build Coastguard Worker if (!static_cast<ARMOperand &>(*Operands[op]).isSignedOffset<24, 1>())
6509*9880d681SAndroid Build Coastguard Worker return Error(Operands[op]->getStartLoc(), "branch target out of range");
6510*9880d681SAndroid Build Coastguard Worker break;
6511*9880d681SAndroid Build Coastguard Worker }
6512*9880d681SAndroid Build Coastguard Worker // Final range checking for Thumb conditional branch instructions.
6513*9880d681SAndroid Build Coastguard Worker case ARM::tBcc:
6514*9880d681SAndroid Build Coastguard Worker if (!static_cast<ARMOperand &>(*Operands[2]).isSignedOffset<8, 1>())
6515*9880d681SAndroid Build Coastguard Worker return Error(Operands[2]->getStartLoc(), "branch target out of range");
6516*9880d681SAndroid Build Coastguard Worker break;
6517*9880d681SAndroid Build Coastguard Worker case ARM::t2Bcc: {
6518*9880d681SAndroid Build Coastguard Worker int Op = (Operands[2]->isImm()) ? 2 : 3;
6519*9880d681SAndroid Build Coastguard Worker if (!static_cast<ARMOperand &>(*Operands[Op]).isSignedOffset<20, 1>())
6520*9880d681SAndroid Build Coastguard Worker return Error(Operands[Op]->getStartLoc(), "branch target out of range");
6521*9880d681SAndroid Build Coastguard Worker break;
6522*9880d681SAndroid Build Coastguard Worker }
6523*9880d681SAndroid Build Coastguard Worker case ARM::MOVi16:
6524*9880d681SAndroid Build Coastguard Worker case ARM::t2MOVi16:
6525*9880d681SAndroid Build Coastguard Worker case ARM::t2MOVTi16:
6526*9880d681SAndroid Build Coastguard Worker {
6527*9880d681SAndroid Build Coastguard Worker // We want to avoid misleadingly allowing something like "mov r0, <symbol>"
6528*9880d681SAndroid Build Coastguard Worker // especially when we turn it into a movw and the expression <symbol> does
6529*9880d681SAndroid Build Coastguard Worker // not have a :lower16: or :upper16 as part of the expression. We don't
6530*9880d681SAndroid Build Coastguard Worker // want the behavior of silently truncating, which can be unexpected and
6531*9880d681SAndroid Build Coastguard Worker // lead to bugs that are difficult to find since this is an easy mistake
6532*9880d681SAndroid Build Coastguard Worker // to make.
6533*9880d681SAndroid Build Coastguard Worker int i = (Operands[3]->isImm()) ? 3 : 4;
6534*9880d681SAndroid Build Coastguard Worker ARMOperand &Op = static_cast<ARMOperand &>(*Operands[i]);
6535*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
6536*9880d681SAndroid Build Coastguard Worker if (CE) break;
6537*9880d681SAndroid Build Coastguard Worker const MCExpr *E = dyn_cast<MCExpr>(Op.getImm());
6538*9880d681SAndroid Build Coastguard Worker if (!E) break;
6539*9880d681SAndroid Build Coastguard Worker const ARMMCExpr *ARM16Expr = dyn_cast<ARMMCExpr>(E);
6540*9880d681SAndroid Build Coastguard Worker if (!ARM16Expr || (ARM16Expr->getKind() != ARMMCExpr::VK_ARM_HI16 &&
6541*9880d681SAndroid Build Coastguard Worker ARM16Expr->getKind() != ARMMCExpr::VK_ARM_LO16))
6542*9880d681SAndroid Build Coastguard Worker return Error(
6543*9880d681SAndroid Build Coastguard Worker Op.getStartLoc(),
6544*9880d681SAndroid Build Coastguard Worker "immediate expression for mov requires :lower16: or :upper16");
6545*9880d681SAndroid Build Coastguard Worker break;
6546*9880d681SAndroid Build Coastguard Worker }
6547*9880d681SAndroid Build Coastguard Worker case ARM::HINT:
6548*9880d681SAndroid Build Coastguard Worker case ARM::t2HINT: {
6549*9880d681SAndroid Build Coastguard Worker if (hasRAS()) {
6550*9880d681SAndroid Build Coastguard Worker // ESB is not predicable (pred must be AL)
6551*9880d681SAndroid Build Coastguard Worker unsigned Imm8 = Inst.getOperand(0).getImm();
6552*9880d681SAndroid Build Coastguard Worker unsigned Pred = Inst.getOperand(1).getImm();
6553*9880d681SAndroid Build Coastguard Worker if (Imm8 == 0x10 && Pred != ARMCC::AL)
6554*9880d681SAndroid Build Coastguard Worker return Error(Operands[1]->getStartLoc(), "instruction 'esb' is not "
6555*9880d681SAndroid Build Coastguard Worker "predicable, but condition "
6556*9880d681SAndroid Build Coastguard Worker "code specified");
6557*9880d681SAndroid Build Coastguard Worker }
6558*9880d681SAndroid Build Coastguard Worker // Without the RAS extension, this behaves as any other unallocated hint.
6559*9880d681SAndroid Build Coastguard Worker break;
6560*9880d681SAndroid Build Coastguard Worker }
6561*9880d681SAndroid Build Coastguard Worker }
6562*9880d681SAndroid Build Coastguard Worker
6563*9880d681SAndroid Build Coastguard Worker return false;
6564*9880d681SAndroid Build Coastguard Worker }
6565*9880d681SAndroid Build Coastguard Worker
getRealVSTOpcode(unsigned Opc,unsigned & Spacing)6566*9880d681SAndroid Build Coastguard Worker static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
6567*9880d681SAndroid Build Coastguard Worker switch(Opc) {
6568*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode!");
6569*9880d681SAndroid Build Coastguard Worker // VST1LN
6570*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
6571*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
6572*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
6573*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
6574*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
6575*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
6576*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
6577*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
6578*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
6579*9880d681SAndroid Build Coastguard Worker
6580*9880d681SAndroid Build Coastguard Worker // VST2LN
6581*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
6582*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
6583*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
6584*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
6585*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
6586*9880d681SAndroid Build Coastguard Worker
6587*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
6588*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
6589*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
6590*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
6591*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
6592*9880d681SAndroid Build Coastguard Worker
6593*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
6594*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
6595*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
6596*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
6597*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
6598*9880d681SAndroid Build Coastguard Worker
6599*9880d681SAndroid Build Coastguard Worker // VST3LN
6600*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
6601*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
6602*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
6603*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
6604*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
6605*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
6606*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
6607*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
6608*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
6609*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
6610*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
6611*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
6612*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
6613*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
6614*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
6615*9880d681SAndroid Build Coastguard Worker
6616*9880d681SAndroid Build Coastguard Worker // VST3
6617*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
6618*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
6619*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
6620*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
6621*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
6622*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
6623*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
6624*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
6625*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
6626*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
6627*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
6628*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
6629*9880d681SAndroid Build Coastguard Worker case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
6630*9880d681SAndroid Build Coastguard Worker case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
6631*9880d681SAndroid Build Coastguard Worker case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
6632*9880d681SAndroid Build Coastguard Worker case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
6633*9880d681SAndroid Build Coastguard Worker case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
6634*9880d681SAndroid Build Coastguard Worker case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
6635*9880d681SAndroid Build Coastguard Worker
6636*9880d681SAndroid Build Coastguard Worker // VST4LN
6637*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
6638*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
6639*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
6640*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
6641*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
6642*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
6643*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
6644*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
6645*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
6646*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
6647*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
6648*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
6649*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
6650*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
6651*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
6652*9880d681SAndroid Build Coastguard Worker
6653*9880d681SAndroid Build Coastguard Worker // VST4
6654*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
6655*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
6656*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
6657*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
6658*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
6659*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
6660*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
6661*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
6662*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
6663*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
6664*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
6665*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
6666*9880d681SAndroid Build Coastguard Worker case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
6667*9880d681SAndroid Build Coastguard Worker case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
6668*9880d681SAndroid Build Coastguard Worker case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
6669*9880d681SAndroid Build Coastguard Worker case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
6670*9880d681SAndroid Build Coastguard Worker case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
6671*9880d681SAndroid Build Coastguard Worker case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
6672*9880d681SAndroid Build Coastguard Worker }
6673*9880d681SAndroid Build Coastguard Worker }
6674*9880d681SAndroid Build Coastguard Worker
getRealVLDOpcode(unsigned Opc,unsigned & Spacing)6675*9880d681SAndroid Build Coastguard Worker static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
6676*9880d681SAndroid Build Coastguard Worker switch(Opc) {
6677*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode!");
6678*9880d681SAndroid Build Coastguard Worker // VLD1LN
6679*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
6680*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
6681*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
6682*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
6683*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
6684*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
6685*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
6686*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
6687*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
6688*9880d681SAndroid Build Coastguard Worker
6689*9880d681SAndroid Build Coastguard Worker // VLD2LN
6690*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
6691*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
6692*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
6693*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
6694*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
6695*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
6696*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
6697*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
6698*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
6699*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
6700*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
6701*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
6702*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
6703*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
6704*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
6705*9880d681SAndroid Build Coastguard Worker
6706*9880d681SAndroid Build Coastguard Worker // VLD3DUP
6707*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
6708*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
6709*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
6710*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
6711*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
6712*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
6713*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
6714*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
6715*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
6716*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
6717*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
6718*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
6719*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
6720*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
6721*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
6722*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
6723*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
6724*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
6725*9880d681SAndroid Build Coastguard Worker
6726*9880d681SAndroid Build Coastguard Worker // VLD3LN
6727*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
6728*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
6729*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
6730*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
6731*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
6732*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
6733*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
6734*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
6735*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
6736*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
6737*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
6738*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
6739*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
6740*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
6741*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
6742*9880d681SAndroid Build Coastguard Worker
6743*9880d681SAndroid Build Coastguard Worker // VLD3
6744*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
6745*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
6746*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
6747*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
6748*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
6749*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
6750*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
6751*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
6752*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
6753*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
6754*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
6755*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
6756*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
6757*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
6758*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
6759*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
6760*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
6761*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
6762*9880d681SAndroid Build Coastguard Worker
6763*9880d681SAndroid Build Coastguard Worker // VLD4LN
6764*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
6765*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
6766*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
6767*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
6768*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
6769*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
6770*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
6771*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
6772*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
6773*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
6774*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
6775*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
6776*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
6777*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
6778*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
6779*9880d681SAndroid Build Coastguard Worker
6780*9880d681SAndroid Build Coastguard Worker // VLD4DUP
6781*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
6782*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
6783*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
6784*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
6785*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
6786*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
6787*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
6788*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
6789*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
6790*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
6791*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
6792*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
6793*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
6794*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
6795*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
6796*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
6797*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
6798*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
6799*9880d681SAndroid Build Coastguard Worker
6800*9880d681SAndroid Build Coastguard Worker // VLD4
6801*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
6802*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
6803*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
6804*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
6805*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
6806*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
6807*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
6808*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
6809*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
6810*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
6811*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
6812*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
6813*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
6814*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
6815*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
6816*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
6817*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
6818*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
6819*9880d681SAndroid Build Coastguard Worker }
6820*9880d681SAndroid Build Coastguard Worker }
6821*9880d681SAndroid Build Coastguard Worker
processInstruction(MCInst & Inst,const OperandVector & Operands,MCStreamer & Out)6822*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::processInstruction(MCInst &Inst,
6823*9880d681SAndroid Build Coastguard Worker const OperandVector &Operands,
6824*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) {
6825*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
6826*9880d681SAndroid Build Coastguard Worker // Alias for alternate form of 'ldr{,b}t Rt, [Rn], #imm' instruction.
6827*9880d681SAndroid Build Coastguard Worker case ARM::LDRT_POST:
6828*9880d681SAndroid Build Coastguard Worker case ARM::LDRBT_POST: {
6829*9880d681SAndroid Build Coastguard Worker const unsigned Opcode =
6830*9880d681SAndroid Build Coastguard Worker (Inst.getOpcode() == ARM::LDRT_POST) ? ARM::LDRT_POST_IMM
6831*9880d681SAndroid Build Coastguard Worker : ARM::LDRBT_POST_IMM;
6832*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
6833*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(Opcode);
6834*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
6835*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
6836*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
6837*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0));
6838*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(0));
6839*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
6840*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
6841*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
6842*9880d681SAndroid Build Coastguard Worker return true;
6843*9880d681SAndroid Build Coastguard Worker }
6844*9880d681SAndroid Build Coastguard Worker // Alias for alternate form of 'str{,b}t Rt, [Rn], #imm' instruction.
6845*9880d681SAndroid Build Coastguard Worker case ARM::STRT_POST:
6846*9880d681SAndroid Build Coastguard Worker case ARM::STRBT_POST: {
6847*9880d681SAndroid Build Coastguard Worker const unsigned Opcode =
6848*9880d681SAndroid Build Coastguard Worker (Inst.getOpcode() == ARM::STRT_POST) ? ARM::STRT_POST_IMM
6849*9880d681SAndroid Build Coastguard Worker : ARM::STRBT_POST_IMM;
6850*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
6851*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(Opcode);
6852*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
6853*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
6854*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
6855*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0));
6856*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(0));
6857*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
6858*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
6859*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
6860*9880d681SAndroid Build Coastguard Worker return true;
6861*9880d681SAndroid Build Coastguard Worker }
6862*9880d681SAndroid Build Coastguard Worker // Alias for alternate form of 'ADR Rd, #imm' instruction.
6863*9880d681SAndroid Build Coastguard Worker case ARM::ADDri: {
6864*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(1).getReg() != ARM::PC ||
6865*9880d681SAndroid Build Coastguard Worker Inst.getOperand(5).getReg() != 0 ||
6866*9880d681SAndroid Build Coastguard Worker !(Inst.getOperand(2).isExpr() || Inst.getOperand(2).isImm()))
6867*9880d681SAndroid Build Coastguard Worker return false;
6868*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
6869*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::ADR);
6870*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
6871*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(2).isImm()) {
6872*9880d681SAndroid Build Coastguard Worker // Immediate (mod_imm) will be in its encoded form, we must unencode it
6873*9880d681SAndroid Build Coastguard Worker // before passing it to the ADR instruction.
6874*9880d681SAndroid Build Coastguard Worker unsigned Enc = Inst.getOperand(2).getImm();
6875*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(
6876*9880d681SAndroid Build Coastguard Worker ARM_AM::rotr32(Enc & 0xFF, (Enc & 0xF00) >> 7)));
6877*9880d681SAndroid Build Coastguard Worker } else {
6878*9880d681SAndroid Build Coastguard Worker // Turn PC-relative expression into absolute expression.
6879*9880d681SAndroid Build Coastguard Worker // Reading PC provides the start of the current instruction + 8 and
6880*9880d681SAndroid Build Coastguard Worker // the transform to adr is biased by that.
6881*9880d681SAndroid Build Coastguard Worker MCSymbol *Dot = getContext().createTempSymbol();
6882*9880d681SAndroid Build Coastguard Worker Out.EmitLabel(Dot);
6883*9880d681SAndroid Build Coastguard Worker const MCExpr *OpExpr = Inst.getOperand(2).getExpr();
6884*9880d681SAndroid Build Coastguard Worker const MCExpr *InstPC = MCSymbolRefExpr::create(Dot,
6885*9880d681SAndroid Build Coastguard Worker MCSymbolRefExpr::VK_None,
6886*9880d681SAndroid Build Coastguard Worker getContext());
6887*9880d681SAndroid Build Coastguard Worker const MCExpr *Const8 = MCConstantExpr::create(8, getContext());
6888*9880d681SAndroid Build Coastguard Worker const MCExpr *ReadPC = MCBinaryExpr::createAdd(InstPC, Const8,
6889*9880d681SAndroid Build Coastguard Worker getContext());
6890*9880d681SAndroid Build Coastguard Worker const MCExpr *FixupAddr = MCBinaryExpr::createAdd(ReadPC, OpExpr,
6891*9880d681SAndroid Build Coastguard Worker getContext());
6892*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createExpr(FixupAddr));
6893*9880d681SAndroid Build Coastguard Worker }
6894*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
6895*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
6896*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
6897*9880d681SAndroid Build Coastguard Worker return true;
6898*9880d681SAndroid Build Coastguard Worker }
6899*9880d681SAndroid Build Coastguard Worker // Aliases for alternate PC+imm syntax of LDR instructions.
6900*9880d681SAndroid Build Coastguard Worker case ARM::t2LDRpcrel:
6901*9880d681SAndroid Build Coastguard Worker // Select the narrow version if the immediate will fit.
6902*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(1).getImm() > 0 &&
6903*9880d681SAndroid Build Coastguard Worker Inst.getOperand(1).getImm() <= 0xff &&
6904*9880d681SAndroid Build Coastguard Worker !(static_cast<ARMOperand &>(*Operands[2]).isToken() &&
6905*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[2]).getToken() == ".w"))
6906*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::tLDRpci);
6907*9880d681SAndroid Build Coastguard Worker else
6908*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2LDRpci);
6909*9880d681SAndroid Build Coastguard Worker return true;
6910*9880d681SAndroid Build Coastguard Worker case ARM::t2LDRBpcrel:
6911*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2LDRBpci);
6912*9880d681SAndroid Build Coastguard Worker return true;
6913*9880d681SAndroid Build Coastguard Worker case ARM::t2LDRHpcrel:
6914*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2LDRHpci);
6915*9880d681SAndroid Build Coastguard Worker return true;
6916*9880d681SAndroid Build Coastguard Worker case ARM::t2LDRSBpcrel:
6917*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2LDRSBpci);
6918*9880d681SAndroid Build Coastguard Worker return true;
6919*9880d681SAndroid Build Coastguard Worker case ARM::t2LDRSHpcrel:
6920*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2LDRSHpci);
6921*9880d681SAndroid Build Coastguard Worker return true;
6922*9880d681SAndroid Build Coastguard Worker case ARM::LDRConstPool:
6923*9880d681SAndroid Build Coastguard Worker case ARM::tLDRConstPool:
6924*9880d681SAndroid Build Coastguard Worker case ARM::t2LDRConstPool: {
6925*9880d681SAndroid Build Coastguard Worker // Pseudo instruction ldr rt, =immediate is converted to a
6926*9880d681SAndroid Build Coastguard Worker // MOV rt, immediate if immediate is known and representable
6927*9880d681SAndroid Build Coastguard Worker // otherwise we create a constant pool entry that we load from.
6928*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
6929*9880d681SAndroid Build Coastguard Worker if (Inst.getOpcode() == ARM::LDRConstPool)
6930*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::LDRi12);
6931*9880d681SAndroid Build Coastguard Worker else if (Inst.getOpcode() == ARM::tLDRConstPool)
6932*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::tLDRpci);
6933*9880d681SAndroid Build Coastguard Worker else if (Inst.getOpcode() == ARM::t2LDRConstPool)
6934*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::t2LDRpci);
6935*9880d681SAndroid Build Coastguard Worker const ARMOperand &PoolOperand =
6936*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]);
6937*9880d681SAndroid Build Coastguard Worker const MCExpr *SubExprVal = PoolOperand.getConstantPoolImm();
6938*9880d681SAndroid Build Coastguard Worker // If SubExprVal is a constant we may be able to use a MOV
6939*9880d681SAndroid Build Coastguard Worker if (isa<MCConstantExpr>(SubExprVal) &&
6940*9880d681SAndroid Build Coastguard Worker Inst.getOperand(0).getReg() != ARM::PC &&
6941*9880d681SAndroid Build Coastguard Worker Inst.getOperand(0).getReg() != ARM::SP) {
6942*9880d681SAndroid Build Coastguard Worker int64_t Value =
6943*9880d681SAndroid Build Coastguard Worker (int64_t) (cast<MCConstantExpr>(SubExprVal))->getValue();
6944*9880d681SAndroid Build Coastguard Worker bool UseMov = true;
6945*9880d681SAndroid Build Coastguard Worker bool MovHasS = true;
6946*9880d681SAndroid Build Coastguard Worker if (Inst.getOpcode() == ARM::LDRConstPool) {
6947*9880d681SAndroid Build Coastguard Worker // ARM Constant
6948*9880d681SAndroid Build Coastguard Worker if (ARM_AM::getSOImmVal(Value) != -1) {
6949*9880d681SAndroid Build Coastguard Worker Value = ARM_AM::getSOImmVal(Value);
6950*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::MOVi);
6951*9880d681SAndroid Build Coastguard Worker }
6952*9880d681SAndroid Build Coastguard Worker else if (ARM_AM::getSOImmVal(~Value) != -1) {
6953*9880d681SAndroid Build Coastguard Worker Value = ARM_AM::getSOImmVal(~Value);
6954*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::MVNi);
6955*9880d681SAndroid Build Coastguard Worker }
6956*9880d681SAndroid Build Coastguard Worker else if (hasV6T2Ops() &&
6957*9880d681SAndroid Build Coastguard Worker Value >=0 && Value < 65536) {
6958*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::MOVi16);
6959*9880d681SAndroid Build Coastguard Worker MovHasS = false;
6960*9880d681SAndroid Build Coastguard Worker }
6961*9880d681SAndroid Build Coastguard Worker else
6962*9880d681SAndroid Build Coastguard Worker UseMov = false;
6963*9880d681SAndroid Build Coastguard Worker }
6964*9880d681SAndroid Build Coastguard Worker else {
6965*9880d681SAndroid Build Coastguard Worker // Thumb/Thumb2 Constant
6966*9880d681SAndroid Build Coastguard Worker if (hasThumb2() &&
6967*9880d681SAndroid Build Coastguard Worker ARM_AM::getT2SOImmVal(Value) != -1)
6968*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::t2MOVi);
6969*9880d681SAndroid Build Coastguard Worker else if (hasThumb2() &&
6970*9880d681SAndroid Build Coastguard Worker ARM_AM::getT2SOImmVal(~Value) != -1) {
6971*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::t2MVNi);
6972*9880d681SAndroid Build Coastguard Worker Value = ~Value;
6973*9880d681SAndroid Build Coastguard Worker }
6974*9880d681SAndroid Build Coastguard Worker else if (hasV8MBaseline() &&
6975*9880d681SAndroid Build Coastguard Worker Value >=0 && Value < 65536) {
6976*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::t2MOVi16);
6977*9880d681SAndroid Build Coastguard Worker MovHasS = false;
6978*9880d681SAndroid Build Coastguard Worker }
6979*9880d681SAndroid Build Coastguard Worker else
6980*9880d681SAndroid Build Coastguard Worker UseMov = false;
6981*9880d681SAndroid Build Coastguard Worker }
6982*9880d681SAndroid Build Coastguard Worker if (UseMov) {
6983*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rt
6984*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(Value)); // Immediate
6985*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6986*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6987*9880d681SAndroid Build Coastguard Worker if (MovHasS)
6988*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // S
6989*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
6990*9880d681SAndroid Build Coastguard Worker return true;
6991*9880d681SAndroid Build Coastguard Worker }
6992*9880d681SAndroid Build Coastguard Worker }
6993*9880d681SAndroid Build Coastguard Worker // No opportunity to use MOV/MVN create constant pool
6994*9880d681SAndroid Build Coastguard Worker const MCExpr *CPLoc =
6995*9880d681SAndroid Build Coastguard Worker getTargetStreamer().addConstantPoolEntry(SubExprVal,
6996*9880d681SAndroid Build Coastguard Worker PoolOperand.getStartLoc());
6997*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rt
6998*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createExpr(CPLoc)); // offset to constpool
6999*9880d681SAndroid Build Coastguard Worker if (TmpInst.getOpcode() == ARM::LDRi12)
7000*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(0)); // unused offset
7001*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // CondCode
7002*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7003*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7004*9880d681SAndroid Build Coastguard Worker return true;
7005*9880d681SAndroid Build Coastguard Worker }
7006*9880d681SAndroid Build Coastguard Worker // Handle NEON VST complex aliases.
7007*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_register_Asm_8:
7008*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_register_Asm_16:
7009*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_register_Asm_32: {
7010*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7011*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7012*9880d681SAndroid Build Coastguard Worker // right place.
7013*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7014*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7015*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7016*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7017*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7018*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rm
7019*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7020*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7021*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // CondCode
7022*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(6));
7023*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7024*9880d681SAndroid Build Coastguard Worker return true;
7025*9880d681SAndroid Build Coastguard Worker }
7026*9880d681SAndroid Build Coastguard Worker
7027*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_register_Asm_8:
7028*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_register_Asm_16:
7029*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_register_Asm_32:
7030*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqWB_register_Asm_16:
7031*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqWB_register_Asm_32: {
7032*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7033*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7034*9880d681SAndroid Build Coastguard Worker // right place.
7035*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7036*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7037*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7038*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7039*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7040*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rm
7041*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7042*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7043*9880d681SAndroid Build Coastguard Worker Spacing));
7044*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7045*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // CondCode
7046*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(6));
7047*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7048*9880d681SAndroid Build Coastguard Worker return true;
7049*9880d681SAndroid Build Coastguard Worker }
7050*9880d681SAndroid Build Coastguard Worker
7051*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_register_Asm_8:
7052*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_register_Asm_16:
7053*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_register_Asm_32:
7054*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqWB_register_Asm_16:
7055*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqWB_register_Asm_32: {
7056*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7057*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7058*9880d681SAndroid Build Coastguard Worker // right place.
7059*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7060*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7061*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7062*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7063*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7064*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rm
7065*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7066*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7067*9880d681SAndroid Build Coastguard Worker Spacing));
7068*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7069*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7070*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7071*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // CondCode
7072*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(6));
7073*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7074*9880d681SAndroid Build Coastguard Worker return true;
7075*9880d681SAndroid Build Coastguard Worker }
7076*9880d681SAndroid Build Coastguard Worker
7077*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_register_Asm_8:
7078*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_register_Asm_16:
7079*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_register_Asm_32:
7080*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqWB_register_Asm_16:
7081*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqWB_register_Asm_32: {
7082*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7083*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7084*9880d681SAndroid Build Coastguard Worker // right place.
7085*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7086*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7087*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7088*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7089*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7090*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rm
7091*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7092*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7093*9880d681SAndroid Build Coastguard Worker Spacing));
7094*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7095*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7096*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7097*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7098*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7099*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // CondCode
7100*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(6));
7101*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7102*9880d681SAndroid Build Coastguard Worker return true;
7103*9880d681SAndroid Build Coastguard Worker }
7104*9880d681SAndroid Build Coastguard Worker
7105*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_fixed_Asm_8:
7106*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_fixed_Asm_16:
7107*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdWB_fixed_Asm_32: {
7108*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7109*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7110*9880d681SAndroid Build Coastguard Worker // right place.
7111*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7112*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7113*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7114*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7115*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7116*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7117*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7118*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7119*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7120*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7121*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7122*9880d681SAndroid Build Coastguard Worker return true;
7123*9880d681SAndroid Build Coastguard Worker }
7124*9880d681SAndroid Build Coastguard Worker
7125*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_fixed_Asm_8:
7126*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_fixed_Asm_16:
7127*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdWB_fixed_Asm_32:
7128*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqWB_fixed_Asm_16:
7129*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqWB_fixed_Asm_32: {
7130*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7131*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7132*9880d681SAndroid Build Coastguard Worker // right place.
7133*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7134*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7135*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7136*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7137*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7138*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7139*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7140*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7141*9880d681SAndroid Build Coastguard Worker Spacing));
7142*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7143*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7144*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7145*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7146*9880d681SAndroid Build Coastguard Worker return true;
7147*9880d681SAndroid Build Coastguard Worker }
7148*9880d681SAndroid Build Coastguard Worker
7149*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_fixed_Asm_8:
7150*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_fixed_Asm_16:
7151*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdWB_fixed_Asm_32:
7152*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqWB_fixed_Asm_16:
7153*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqWB_fixed_Asm_32: {
7154*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7155*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7156*9880d681SAndroid Build Coastguard Worker // right place.
7157*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7158*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7159*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7160*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7161*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7162*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7163*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7164*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7165*9880d681SAndroid Build Coastguard Worker Spacing));
7166*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7167*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7168*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7169*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7170*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7171*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7172*9880d681SAndroid Build Coastguard Worker return true;
7173*9880d681SAndroid Build Coastguard Worker }
7174*9880d681SAndroid Build Coastguard Worker
7175*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_fixed_Asm_8:
7176*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_fixed_Asm_16:
7177*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdWB_fixed_Asm_32:
7178*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqWB_fixed_Asm_16:
7179*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqWB_fixed_Asm_32: {
7180*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7181*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7182*9880d681SAndroid Build Coastguard Worker // right place.
7183*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7184*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7185*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7186*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7187*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7188*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7189*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7190*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7191*9880d681SAndroid Build Coastguard Worker Spacing));
7192*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7193*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7194*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7195*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7196*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7197*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7198*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7199*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7200*9880d681SAndroid Build Coastguard Worker return true;
7201*9880d681SAndroid Build Coastguard Worker }
7202*9880d681SAndroid Build Coastguard Worker
7203*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdAsm_8:
7204*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdAsm_16:
7205*9880d681SAndroid Build Coastguard Worker case ARM::VST1LNdAsm_32: {
7206*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7207*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7208*9880d681SAndroid Build Coastguard Worker // right place.
7209*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7210*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7211*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7212*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7213*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7214*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7215*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7216*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7217*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7218*9880d681SAndroid Build Coastguard Worker return true;
7219*9880d681SAndroid Build Coastguard Worker }
7220*9880d681SAndroid Build Coastguard Worker
7221*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdAsm_8:
7222*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdAsm_16:
7223*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNdAsm_32:
7224*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqAsm_16:
7225*9880d681SAndroid Build Coastguard Worker case ARM::VST2LNqAsm_32: {
7226*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7227*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7228*9880d681SAndroid Build Coastguard Worker // right place.
7229*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7230*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7231*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7232*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7233*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7234*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7235*9880d681SAndroid Build Coastguard Worker Spacing));
7236*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7237*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7238*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7239*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7240*9880d681SAndroid Build Coastguard Worker return true;
7241*9880d681SAndroid Build Coastguard Worker }
7242*9880d681SAndroid Build Coastguard Worker
7243*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdAsm_8:
7244*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdAsm_16:
7245*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNdAsm_32:
7246*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqAsm_16:
7247*9880d681SAndroid Build Coastguard Worker case ARM::VST3LNqAsm_32: {
7248*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7249*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7250*9880d681SAndroid Build Coastguard Worker // right place.
7251*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7252*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7253*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7254*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7255*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7256*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7257*9880d681SAndroid Build Coastguard Worker Spacing));
7258*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7259*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7260*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7261*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7262*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7263*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7264*9880d681SAndroid Build Coastguard Worker return true;
7265*9880d681SAndroid Build Coastguard Worker }
7266*9880d681SAndroid Build Coastguard Worker
7267*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdAsm_8:
7268*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdAsm_16:
7269*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNdAsm_32:
7270*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqAsm_16:
7271*9880d681SAndroid Build Coastguard Worker case ARM::VST4LNqAsm_32: {
7272*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7273*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7274*9880d681SAndroid Build Coastguard Worker // right place.
7275*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7276*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7277*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7278*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7279*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7280*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7281*9880d681SAndroid Build Coastguard Worker Spacing));
7282*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7283*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7284*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7285*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7286*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7287*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7288*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7289*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7290*9880d681SAndroid Build Coastguard Worker return true;
7291*9880d681SAndroid Build Coastguard Worker }
7292*9880d681SAndroid Build Coastguard Worker
7293*9880d681SAndroid Build Coastguard Worker // Handle NEON VLD complex aliases.
7294*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_register_Asm_8:
7295*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_register_Asm_16:
7296*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_register_Asm_32: {
7297*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7298*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7299*9880d681SAndroid Build Coastguard Worker // right place.
7300*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7301*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7302*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7303*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7304*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7305*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7306*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rm
7307*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7308*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7309*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // CondCode
7310*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(6));
7311*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7312*9880d681SAndroid Build Coastguard Worker return true;
7313*9880d681SAndroid Build Coastguard Worker }
7314*9880d681SAndroid Build Coastguard Worker
7315*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_register_Asm_8:
7316*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_register_Asm_16:
7317*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_register_Asm_32:
7318*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqWB_register_Asm_16:
7319*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqWB_register_Asm_32: {
7320*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7321*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7322*9880d681SAndroid Build Coastguard Worker // right place.
7323*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7324*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7325*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7326*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7327*9880d681SAndroid Build Coastguard Worker Spacing));
7328*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7329*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7330*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7331*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rm
7332*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7333*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7334*9880d681SAndroid Build Coastguard Worker Spacing));
7335*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7336*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // CondCode
7337*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(6));
7338*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7339*9880d681SAndroid Build Coastguard Worker return true;
7340*9880d681SAndroid Build Coastguard Worker }
7341*9880d681SAndroid Build Coastguard Worker
7342*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_register_Asm_8:
7343*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_register_Asm_16:
7344*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_register_Asm_32:
7345*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqWB_register_Asm_16:
7346*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqWB_register_Asm_32: {
7347*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7348*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7349*9880d681SAndroid Build Coastguard Worker // right place.
7350*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7351*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7352*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7353*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7354*9880d681SAndroid Build Coastguard Worker Spacing));
7355*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7356*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7357*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7358*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7359*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7360*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rm
7361*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7362*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7363*9880d681SAndroid Build Coastguard Worker Spacing));
7364*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7365*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7366*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7367*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // CondCode
7368*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(6));
7369*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7370*9880d681SAndroid Build Coastguard Worker return true;
7371*9880d681SAndroid Build Coastguard Worker }
7372*9880d681SAndroid Build Coastguard Worker
7373*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_register_Asm_8:
7374*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_register_Asm_16:
7375*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_register_Asm_32:
7376*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqWB_register_Asm_16:
7377*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqWB_register_Asm_32: {
7378*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7379*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7380*9880d681SAndroid Build Coastguard Worker // right place.
7381*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7382*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7383*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7384*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7385*9880d681SAndroid Build Coastguard Worker Spacing));
7386*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7387*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7388*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7389*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7390*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7391*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7392*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7393*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rm
7394*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7395*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7396*9880d681SAndroid Build Coastguard Worker Spacing));
7397*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7398*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7399*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7400*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7401*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7402*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // CondCode
7403*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(6));
7404*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7405*9880d681SAndroid Build Coastguard Worker return true;
7406*9880d681SAndroid Build Coastguard Worker }
7407*9880d681SAndroid Build Coastguard Worker
7408*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_fixed_Asm_8:
7409*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_fixed_Asm_16:
7410*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdWB_fixed_Asm_32: {
7411*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7412*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7413*9880d681SAndroid Build Coastguard Worker // right place.
7414*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7415*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7416*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7417*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7418*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7419*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7420*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7421*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7422*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7423*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7424*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7425*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7426*9880d681SAndroid Build Coastguard Worker return true;
7427*9880d681SAndroid Build Coastguard Worker }
7428*9880d681SAndroid Build Coastguard Worker
7429*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_fixed_Asm_8:
7430*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_fixed_Asm_16:
7431*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdWB_fixed_Asm_32:
7432*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqWB_fixed_Asm_16:
7433*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqWB_fixed_Asm_32: {
7434*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7435*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7436*9880d681SAndroid Build Coastguard Worker // right place.
7437*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7438*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7439*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7440*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7441*9880d681SAndroid Build Coastguard Worker Spacing));
7442*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7443*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7444*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7445*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7446*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7447*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7448*9880d681SAndroid Build Coastguard Worker Spacing));
7449*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7450*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7451*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7452*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7453*9880d681SAndroid Build Coastguard Worker return true;
7454*9880d681SAndroid Build Coastguard Worker }
7455*9880d681SAndroid Build Coastguard Worker
7456*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_fixed_Asm_8:
7457*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_fixed_Asm_16:
7458*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdWB_fixed_Asm_32:
7459*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqWB_fixed_Asm_16:
7460*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqWB_fixed_Asm_32: {
7461*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7462*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7463*9880d681SAndroid Build Coastguard Worker // right place.
7464*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7465*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7466*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7467*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7468*9880d681SAndroid Build Coastguard Worker Spacing));
7469*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7470*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7471*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7472*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7473*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7474*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7475*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7476*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7477*9880d681SAndroid Build Coastguard Worker Spacing));
7478*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7479*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7480*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7481*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7482*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7483*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7484*9880d681SAndroid Build Coastguard Worker return true;
7485*9880d681SAndroid Build Coastguard Worker }
7486*9880d681SAndroid Build Coastguard Worker
7487*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_fixed_Asm_8:
7488*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_fixed_Asm_16:
7489*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdWB_fixed_Asm_32:
7490*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqWB_fixed_Asm_16:
7491*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqWB_fixed_Asm_32: {
7492*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7493*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7494*9880d681SAndroid Build Coastguard Worker // right place.
7495*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7496*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7497*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7498*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7499*9880d681SAndroid Build Coastguard Worker Spacing));
7500*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7501*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7502*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7503*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7504*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
7505*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7506*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7507*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7508*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7509*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7510*9880d681SAndroid Build Coastguard Worker Spacing));
7511*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7512*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7513*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7514*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7515*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7516*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7517*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7518*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7519*9880d681SAndroid Build Coastguard Worker return true;
7520*9880d681SAndroid Build Coastguard Worker }
7521*9880d681SAndroid Build Coastguard Worker
7522*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdAsm_8:
7523*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdAsm_16:
7524*9880d681SAndroid Build Coastguard Worker case ARM::VLD1LNdAsm_32: {
7525*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7526*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7527*9880d681SAndroid Build Coastguard Worker // right place.
7528*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7529*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7530*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7531*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7532*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7533*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7534*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7535*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7536*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7537*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7538*9880d681SAndroid Build Coastguard Worker return true;
7539*9880d681SAndroid Build Coastguard Worker }
7540*9880d681SAndroid Build Coastguard Worker
7541*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdAsm_8:
7542*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdAsm_16:
7543*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNdAsm_32:
7544*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqAsm_16:
7545*9880d681SAndroid Build Coastguard Worker case ARM::VLD2LNqAsm_32: {
7546*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7547*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7548*9880d681SAndroid Build Coastguard Worker // right place.
7549*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7550*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7551*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7552*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7553*9880d681SAndroid Build Coastguard Worker Spacing));
7554*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7555*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7556*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7557*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7558*9880d681SAndroid Build Coastguard Worker Spacing));
7559*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7560*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7561*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7562*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7563*9880d681SAndroid Build Coastguard Worker return true;
7564*9880d681SAndroid Build Coastguard Worker }
7565*9880d681SAndroid Build Coastguard Worker
7566*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdAsm_8:
7567*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdAsm_16:
7568*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNdAsm_32:
7569*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqAsm_16:
7570*9880d681SAndroid Build Coastguard Worker case ARM::VLD3LNqAsm_32: {
7571*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7572*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7573*9880d681SAndroid Build Coastguard Worker // right place.
7574*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7575*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7576*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7577*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7578*9880d681SAndroid Build Coastguard Worker Spacing));
7579*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7580*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7581*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7582*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7583*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7584*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7585*9880d681SAndroid Build Coastguard Worker Spacing));
7586*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7587*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7588*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7589*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7590*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7591*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7592*9880d681SAndroid Build Coastguard Worker return true;
7593*9880d681SAndroid Build Coastguard Worker }
7594*9880d681SAndroid Build Coastguard Worker
7595*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdAsm_8:
7596*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdAsm_16:
7597*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNdAsm_32:
7598*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqAsm_16:
7599*9880d681SAndroid Build Coastguard Worker case ARM::VLD4LNqAsm_32: {
7600*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7601*9880d681SAndroid Build Coastguard Worker // Shuffle the operands around so the lane index operand is in the
7602*9880d681SAndroid Build Coastguard Worker // right place.
7603*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7604*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7605*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7606*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7607*9880d681SAndroid Build Coastguard Worker Spacing));
7608*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7609*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7610*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7611*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7612*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rn
7613*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // alignment
7614*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7615*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7616*9880d681SAndroid Build Coastguard Worker Spacing));
7617*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7618*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7619*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7620*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7621*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // lane
7622*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7623*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7624*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7625*9880d681SAndroid Build Coastguard Worker return true;
7626*9880d681SAndroid Build Coastguard Worker }
7627*9880d681SAndroid Build Coastguard Worker
7628*9880d681SAndroid Build Coastguard Worker // VLD3DUP single 3-element structure to all lanes instructions.
7629*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdAsm_8:
7630*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdAsm_16:
7631*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdAsm_32:
7632*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqAsm_8:
7633*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqAsm_16:
7634*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqAsm_32: {
7635*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7636*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7637*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7638*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7639*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7640*9880d681SAndroid Build Coastguard Worker Spacing));
7641*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7642*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7643*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7644*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7645*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7646*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7647*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7648*9880d681SAndroid Build Coastguard Worker return true;
7649*9880d681SAndroid Build Coastguard Worker }
7650*9880d681SAndroid Build Coastguard Worker
7651*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_fixed_Asm_8:
7652*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_fixed_Asm_16:
7653*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_fixed_Asm_32:
7654*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_fixed_Asm_8:
7655*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_fixed_Asm_16:
7656*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_fixed_Asm_32: {
7657*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7658*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7659*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7660*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7661*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7662*9880d681SAndroid Build Coastguard Worker Spacing));
7663*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7664*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7665*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7666*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7667*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7668*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7669*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7670*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7671*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7672*9880d681SAndroid Build Coastguard Worker return true;
7673*9880d681SAndroid Build Coastguard Worker }
7674*9880d681SAndroid Build Coastguard Worker
7675*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_register_Asm_8:
7676*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_register_Asm_16:
7677*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPdWB_register_Asm_32:
7678*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_register_Asm_8:
7679*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_register_Asm_16:
7680*9880d681SAndroid Build Coastguard Worker case ARM::VLD3DUPqWB_register_Asm_32: {
7681*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7682*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7683*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7684*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7685*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7686*9880d681SAndroid Build Coastguard Worker Spacing));
7687*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7688*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7689*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7690*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7691*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7692*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // Rm
7693*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7694*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7695*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7696*9880d681SAndroid Build Coastguard Worker return true;
7697*9880d681SAndroid Build Coastguard Worker }
7698*9880d681SAndroid Build Coastguard Worker
7699*9880d681SAndroid Build Coastguard Worker // VLD3 multiple 3-element structure instructions.
7700*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dAsm_8:
7701*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dAsm_16:
7702*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dAsm_32:
7703*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qAsm_8:
7704*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qAsm_16:
7705*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qAsm_32: {
7706*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7707*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7708*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7709*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7710*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7711*9880d681SAndroid Build Coastguard Worker Spacing));
7712*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7713*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7714*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7715*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7716*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7717*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7718*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7719*9880d681SAndroid Build Coastguard Worker return true;
7720*9880d681SAndroid Build Coastguard Worker }
7721*9880d681SAndroid Build Coastguard Worker
7722*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_fixed_Asm_8:
7723*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_fixed_Asm_16:
7724*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_fixed_Asm_32:
7725*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_fixed_Asm_8:
7726*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_fixed_Asm_16:
7727*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_fixed_Asm_32: {
7728*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7729*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7730*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7731*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7732*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7733*9880d681SAndroid Build Coastguard Worker Spacing));
7734*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7735*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7736*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7737*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7738*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7739*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7740*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7741*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7742*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7743*9880d681SAndroid Build Coastguard Worker return true;
7744*9880d681SAndroid Build Coastguard Worker }
7745*9880d681SAndroid Build Coastguard Worker
7746*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_register_Asm_8:
7747*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_register_Asm_16:
7748*9880d681SAndroid Build Coastguard Worker case ARM::VLD3dWB_register_Asm_32:
7749*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_register_Asm_8:
7750*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_register_Asm_16:
7751*9880d681SAndroid Build Coastguard Worker case ARM::VLD3qWB_register_Asm_32: {
7752*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7753*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7754*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7755*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7756*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7757*9880d681SAndroid Build Coastguard Worker Spacing));
7758*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7759*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7760*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7761*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7762*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7763*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // Rm
7764*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7765*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7766*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7767*9880d681SAndroid Build Coastguard Worker return true;
7768*9880d681SAndroid Build Coastguard Worker }
7769*9880d681SAndroid Build Coastguard Worker
7770*9880d681SAndroid Build Coastguard Worker // VLD4DUP single 3-element structure to all lanes instructions.
7771*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdAsm_8:
7772*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdAsm_16:
7773*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdAsm_32:
7774*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqAsm_8:
7775*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqAsm_16:
7776*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqAsm_32: {
7777*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7778*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7779*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7780*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7781*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7782*9880d681SAndroid Build Coastguard Worker Spacing));
7783*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7784*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7785*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7786*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7787*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7788*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7789*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7790*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7791*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7792*9880d681SAndroid Build Coastguard Worker return true;
7793*9880d681SAndroid Build Coastguard Worker }
7794*9880d681SAndroid Build Coastguard Worker
7795*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_fixed_Asm_8:
7796*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_fixed_Asm_16:
7797*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_fixed_Asm_32:
7798*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_fixed_Asm_8:
7799*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_fixed_Asm_16:
7800*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_fixed_Asm_32: {
7801*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7802*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7803*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7804*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7805*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7806*9880d681SAndroid Build Coastguard Worker Spacing));
7807*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7808*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7809*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7810*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7811*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7812*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7813*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7814*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7815*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7816*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7817*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7818*9880d681SAndroid Build Coastguard Worker return true;
7819*9880d681SAndroid Build Coastguard Worker }
7820*9880d681SAndroid Build Coastguard Worker
7821*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_register_Asm_8:
7822*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_register_Asm_16:
7823*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPdWB_register_Asm_32:
7824*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_register_Asm_8:
7825*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_register_Asm_16:
7826*9880d681SAndroid Build Coastguard Worker case ARM::VLD4DUPqWB_register_Asm_32: {
7827*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7828*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7829*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7830*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7831*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7832*9880d681SAndroid Build Coastguard Worker Spacing));
7833*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7834*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7835*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7836*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7837*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7838*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7839*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7840*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // Rm
7841*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7842*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7843*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7844*9880d681SAndroid Build Coastguard Worker return true;
7845*9880d681SAndroid Build Coastguard Worker }
7846*9880d681SAndroid Build Coastguard Worker
7847*9880d681SAndroid Build Coastguard Worker // VLD4 multiple 4-element structure instructions.
7848*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dAsm_8:
7849*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dAsm_16:
7850*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dAsm_32:
7851*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qAsm_8:
7852*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qAsm_16:
7853*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qAsm_32: {
7854*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7855*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7856*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7857*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7858*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7859*9880d681SAndroid Build Coastguard Worker Spacing));
7860*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7861*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7862*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7863*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7864*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7865*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7866*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7867*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7868*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7869*9880d681SAndroid Build Coastguard Worker return true;
7870*9880d681SAndroid Build Coastguard Worker }
7871*9880d681SAndroid Build Coastguard Worker
7872*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_fixed_Asm_8:
7873*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_fixed_Asm_16:
7874*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_fixed_Asm_32:
7875*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_fixed_Asm_8:
7876*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_fixed_Asm_16:
7877*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_fixed_Asm_32: {
7878*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7879*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7880*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7881*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7882*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7883*9880d681SAndroid Build Coastguard Worker Spacing));
7884*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7885*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7886*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7887*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7888*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7889*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7890*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7891*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7892*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7893*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7894*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7895*9880d681SAndroid Build Coastguard Worker return true;
7896*9880d681SAndroid Build Coastguard Worker }
7897*9880d681SAndroid Build Coastguard Worker
7898*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_register_Asm_8:
7899*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_register_Asm_16:
7900*9880d681SAndroid Build Coastguard Worker case ARM::VLD4dWB_register_Asm_32:
7901*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_register_Asm_8:
7902*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_register_Asm_16:
7903*9880d681SAndroid Build Coastguard Worker case ARM::VLD4qWB_register_Asm_32: {
7904*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7905*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7906*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7907*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7908*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7909*9880d681SAndroid Build Coastguard Worker Spacing));
7910*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7911*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7912*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7913*9880d681SAndroid Build Coastguard Worker Spacing * 3));
7914*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7915*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7916*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7917*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // Rm
7918*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7919*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7920*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7921*9880d681SAndroid Build Coastguard Worker return true;
7922*9880d681SAndroid Build Coastguard Worker }
7923*9880d681SAndroid Build Coastguard Worker
7924*9880d681SAndroid Build Coastguard Worker // VST3 multiple 3-element structure instructions.
7925*9880d681SAndroid Build Coastguard Worker case ARM::VST3dAsm_8:
7926*9880d681SAndroid Build Coastguard Worker case ARM::VST3dAsm_16:
7927*9880d681SAndroid Build Coastguard Worker case ARM::VST3dAsm_32:
7928*9880d681SAndroid Build Coastguard Worker case ARM::VST3qAsm_8:
7929*9880d681SAndroid Build Coastguard Worker case ARM::VST3qAsm_16:
7930*9880d681SAndroid Build Coastguard Worker case ARM::VST3qAsm_32: {
7931*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7932*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7933*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7934*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7935*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7936*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7937*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7938*9880d681SAndroid Build Coastguard Worker Spacing));
7939*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7940*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7941*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7942*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7943*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7944*9880d681SAndroid Build Coastguard Worker return true;
7945*9880d681SAndroid Build Coastguard Worker }
7946*9880d681SAndroid Build Coastguard Worker
7947*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_fixed_Asm_8:
7948*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_fixed_Asm_16:
7949*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_fixed_Asm_32:
7950*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_fixed_Asm_8:
7951*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_fixed_Asm_16:
7952*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_fixed_Asm_32: {
7953*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7954*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7955*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7956*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7957*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7958*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7959*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
7960*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7961*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7962*9880d681SAndroid Build Coastguard Worker Spacing));
7963*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7964*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7965*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7966*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
7967*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7968*9880d681SAndroid Build Coastguard Worker return true;
7969*9880d681SAndroid Build Coastguard Worker }
7970*9880d681SAndroid Build Coastguard Worker
7971*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_register_Asm_8:
7972*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_register_Asm_16:
7973*9880d681SAndroid Build Coastguard Worker case ARM::VST3dWB_register_Asm_32:
7974*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_register_Asm_8:
7975*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_register_Asm_16:
7976*9880d681SAndroid Build Coastguard Worker case ARM::VST3qWB_register_Asm_32: {
7977*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
7978*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
7979*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7980*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
7981*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7982*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
7983*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // Rm
7984*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
7985*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7986*9880d681SAndroid Build Coastguard Worker Spacing));
7987*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
7988*9880d681SAndroid Build Coastguard Worker Spacing * 2));
7989*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7990*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
7991*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
7992*9880d681SAndroid Build Coastguard Worker return true;
7993*9880d681SAndroid Build Coastguard Worker }
7994*9880d681SAndroid Build Coastguard Worker
7995*9880d681SAndroid Build Coastguard Worker // VST4 multiple 3-element structure instructions.
7996*9880d681SAndroid Build Coastguard Worker case ARM::VST4dAsm_8:
7997*9880d681SAndroid Build Coastguard Worker case ARM::VST4dAsm_16:
7998*9880d681SAndroid Build Coastguard Worker case ARM::VST4dAsm_32:
7999*9880d681SAndroid Build Coastguard Worker case ARM::VST4qAsm_8:
8000*9880d681SAndroid Build Coastguard Worker case ARM::VST4qAsm_16:
8001*9880d681SAndroid Build Coastguard Worker case ARM::VST4qAsm_32: {
8002*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8003*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
8004*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
8005*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8006*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
8007*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
8008*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
8009*9880d681SAndroid Build Coastguard Worker Spacing));
8010*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
8011*9880d681SAndroid Build Coastguard Worker Spacing * 2));
8012*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
8013*9880d681SAndroid Build Coastguard Worker Spacing * 3));
8014*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
8015*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8016*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8017*9880d681SAndroid Build Coastguard Worker return true;
8018*9880d681SAndroid Build Coastguard Worker }
8019*9880d681SAndroid Build Coastguard Worker
8020*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_fixed_Asm_8:
8021*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_fixed_Asm_16:
8022*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_fixed_Asm_32:
8023*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_fixed_Asm_8:
8024*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_fixed_Asm_16:
8025*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_fixed_Asm_32: {
8026*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8027*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
8028*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
8029*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8030*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
8031*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
8032*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // Rm
8033*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
8034*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
8035*9880d681SAndroid Build Coastguard Worker Spacing));
8036*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
8037*9880d681SAndroid Build Coastguard Worker Spacing * 2));
8038*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
8039*9880d681SAndroid Build Coastguard Worker Spacing * 3));
8040*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
8041*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8042*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8043*9880d681SAndroid Build Coastguard Worker return true;
8044*9880d681SAndroid Build Coastguard Worker }
8045*9880d681SAndroid Build Coastguard Worker
8046*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_register_Asm_8:
8047*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_register_Asm_16:
8048*9880d681SAndroid Build Coastguard Worker case ARM::VST4dWB_register_Asm_32:
8049*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_register_Asm_8:
8050*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_register_Asm_16:
8051*9880d681SAndroid Build Coastguard Worker case ARM::VST4qWB_register_Asm_32: {
8052*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8053*9880d681SAndroid Build Coastguard Worker unsigned Spacing;
8054*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
8055*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8056*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
8057*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // alignment
8058*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // Rm
8059*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Vd
8060*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
8061*9880d681SAndroid Build Coastguard Worker Spacing));
8062*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
8063*9880d681SAndroid Build Coastguard Worker Spacing * 2));
8064*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() +
8065*9880d681SAndroid Build Coastguard Worker Spacing * 3));
8066*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
8067*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
8068*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8069*9880d681SAndroid Build Coastguard Worker return true;
8070*9880d681SAndroid Build Coastguard Worker }
8071*9880d681SAndroid Build Coastguard Worker
8072*9880d681SAndroid Build Coastguard Worker // Handle encoding choice for the shift-immediate instructions.
8073*9880d681SAndroid Build Coastguard Worker case ARM::t2LSLri:
8074*9880d681SAndroid Build Coastguard Worker case ARM::t2LSRri:
8075*9880d681SAndroid Build Coastguard Worker case ARM::t2ASRri: {
8076*9880d681SAndroid Build Coastguard Worker if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
8077*9880d681SAndroid Build Coastguard Worker Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
8078*9880d681SAndroid Build Coastguard Worker Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
8079*9880d681SAndroid Build Coastguard Worker !(static_cast<ARMOperand &>(*Operands[3]).isToken() &&
8080*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).getToken() == ".w")) {
8081*9880d681SAndroid Build Coastguard Worker unsigned NewOpc;
8082*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
8083*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode");
8084*9880d681SAndroid Build Coastguard Worker case ARM::t2LSLri: NewOpc = ARM::tLSLri; break;
8085*9880d681SAndroid Build Coastguard Worker case ARM::t2LSRri: NewOpc = ARM::tLSRri; break;
8086*9880d681SAndroid Build Coastguard Worker case ARM::t2ASRri: NewOpc = ARM::tASRri; break;
8087*9880d681SAndroid Build Coastguard Worker }
8088*9880d681SAndroid Build Coastguard Worker // The Thumb1 operands aren't in the same order. Awesome, eh?
8089*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8090*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(NewOpc);
8091*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8092*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
8093*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
8094*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
8095*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8096*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8097*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8098*9880d681SAndroid Build Coastguard Worker return true;
8099*9880d681SAndroid Build Coastguard Worker }
8100*9880d681SAndroid Build Coastguard Worker return false;
8101*9880d681SAndroid Build Coastguard Worker }
8102*9880d681SAndroid Build Coastguard Worker
8103*9880d681SAndroid Build Coastguard Worker // Handle the Thumb2 mode MOV complex aliases.
8104*9880d681SAndroid Build Coastguard Worker case ARM::t2MOVsr:
8105*9880d681SAndroid Build Coastguard Worker case ARM::t2MOVSsr: {
8106*9880d681SAndroid Build Coastguard Worker // Which instruction to expand to depends on the CCOut operand and
8107*9880d681SAndroid Build Coastguard Worker // whether we're in an IT block if the register operands are low
8108*9880d681SAndroid Build Coastguard Worker // registers.
8109*9880d681SAndroid Build Coastguard Worker bool isNarrow = false;
8110*9880d681SAndroid Build Coastguard Worker if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
8111*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(1).getReg()) &&
8112*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(2).getReg()) &&
8113*9880d681SAndroid Build Coastguard Worker Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
8114*9880d681SAndroid Build Coastguard Worker inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
8115*9880d681SAndroid Build Coastguard Worker isNarrow = true;
8116*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8117*9880d681SAndroid Build Coastguard Worker unsigned newOpc;
8118*9880d681SAndroid Build Coastguard Worker switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
8119*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode!");
8120*9880d681SAndroid Build Coastguard Worker case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
8121*9880d681SAndroid Build Coastguard Worker case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
8122*9880d681SAndroid Build Coastguard Worker case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
8123*9880d681SAndroid Build Coastguard Worker case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
8124*9880d681SAndroid Build Coastguard Worker }
8125*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(newOpc);
8126*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rd
8127*9880d681SAndroid Build Coastguard Worker if (isNarrow)
8128*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(
8129*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
8130*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8131*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rm
8132*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // CondCode
8133*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
8134*9880d681SAndroid Build Coastguard Worker if (!isNarrow)
8135*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(
8136*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
8137*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8138*9880d681SAndroid Build Coastguard Worker return true;
8139*9880d681SAndroid Build Coastguard Worker }
8140*9880d681SAndroid Build Coastguard Worker case ARM::t2MOVsi:
8141*9880d681SAndroid Build Coastguard Worker case ARM::t2MOVSsi: {
8142*9880d681SAndroid Build Coastguard Worker // Which instruction to expand to depends on the CCOut operand and
8143*9880d681SAndroid Build Coastguard Worker // whether we're in an IT block if the register operands are low
8144*9880d681SAndroid Build Coastguard Worker // registers.
8145*9880d681SAndroid Build Coastguard Worker bool isNarrow = false;
8146*9880d681SAndroid Build Coastguard Worker if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
8147*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(1).getReg()) &&
8148*9880d681SAndroid Build Coastguard Worker inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
8149*9880d681SAndroid Build Coastguard Worker isNarrow = true;
8150*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8151*9880d681SAndroid Build Coastguard Worker unsigned newOpc;
8152*9880d681SAndroid Build Coastguard Worker switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
8153*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode!");
8154*9880d681SAndroid Build Coastguard Worker case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
8155*9880d681SAndroid Build Coastguard Worker case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
8156*9880d681SAndroid Build Coastguard Worker case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
8157*9880d681SAndroid Build Coastguard Worker case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
8158*9880d681SAndroid Build Coastguard Worker case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
8159*9880d681SAndroid Build Coastguard Worker }
8160*9880d681SAndroid Build Coastguard Worker unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
8161*9880d681SAndroid Build Coastguard Worker if (Amount == 32) Amount = 0;
8162*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(newOpc);
8163*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rd
8164*9880d681SAndroid Build Coastguard Worker if (isNarrow)
8165*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(
8166*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
8167*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8168*9880d681SAndroid Build Coastguard Worker if (newOpc != ARM::t2RRX)
8169*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(Amount));
8170*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
8171*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8172*9880d681SAndroid Build Coastguard Worker if (!isNarrow)
8173*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(
8174*9880d681SAndroid Build Coastguard Worker Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
8175*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8176*9880d681SAndroid Build Coastguard Worker return true;
8177*9880d681SAndroid Build Coastguard Worker }
8178*9880d681SAndroid Build Coastguard Worker // Handle the ARM mode MOV complex aliases.
8179*9880d681SAndroid Build Coastguard Worker case ARM::ASRr:
8180*9880d681SAndroid Build Coastguard Worker case ARM::LSRr:
8181*9880d681SAndroid Build Coastguard Worker case ARM::LSLr:
8182*9880d681SAndroid Build Coastguard Worker case ARM::RORr: {
8183*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc ShiftTy;
8184*9880d681SAndroid Build Coastguard Worker switch(Inst.getOpcode()) {
8185*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode!");
8186*9880d681SAndroid Build Coastguard Worker case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
8187*9880d681SAndroid Build Coastguard Worker case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
8188*9880d681SAndroid Build Coastguard Worker case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
8189*9880d681SAndroid Build Coastguard Worker case ARM::RORr: ShiftTy = ARM_AM::ror; break;
8190*9880d681SAndroid Build Coastguard Worker }
8191*9880d681SAndroid Build Coastguard Worker unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
8192*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8193*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::MOVsr);
8194*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rd
8195*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8196*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // Rm
8197*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty
8198*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
8199*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8200*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // cc_out
8201*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8202*9880d681SAndroid Build Coastguard Worker return true;
8203*9880d681SAndroid Build Coastguard Worker }
8204*9880d681SAndroid Build Coastguard Worker case ARM::ASRi:
8205*9880d681SAndroid Build Coastguard Worker case ARM::LSRi:
8206*9880d681SAndroid Build Coastguard Worker case ARM::LSLi:
8207*9880d681SAndroid Build Coastguard Worker case ARM::RORi: {
8208*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc ShiftTy;
8209*9880d681SAndroid Build Coastguard Worker switch(Inst.getOpcode()) {
8210*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode!");
8211*9880d681SAndroid Build Coastguard Worker case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
8212*9880d681SAndroid Build Coastguard Worker case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
8213*9880d681SAndroid Build Coastguard Worker case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
8214*9880d681SAndroid Build Coastguard Worker case ARM::RORi: ShiftTy = ARM_AM::ror; break;
8215*9880d681SAndroid Build Coastguard Worker }
8216*9880d681SAndroid Build Coastguard Worker // A shift by zero is a plain MOVr, not a MOVsi.
8217*9880d681SAndroid Build Coastguard Worker unsigned Amt = Inst.getOperand(2).getImm();
8218*9880d681SAndroid Build Coastguard Worker unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
8219*9880d681SAndroid Build Coastguard Worker // A shift by 32 should be encoded as 0 when permitted
8220*9880d681SAndroid Build Coastguard Worker if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr))
8221*9880d681SAndroid Build Coastguard Worker Amt = 0;
8222*9880d681SAndroid Build Coastguard Worker unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
8223*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8224*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(Opc);
8225*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rd
8226*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8227*9880d681SAndroid Build Coastguard Worker if (Opc == ARM::MOVsi)
8228*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty
8229*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3)); // CondCode
8230*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8231*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5)); // cc_out
8232*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8233*9880d681SAndroid Build Coastguard Worker return true;
8234*9880d681SAndroid Build Coastguard Worker }
8235*9880d681SAndroid Build Coastguard Worker case ARM::RRXi: {
8236*9880d681SAndroid Build Coastguard Worker unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
8237*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8238*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::MOVsi);
8239*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rd
8240*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8241*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty
8242*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // CondCode
8243*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8244*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // cc_out
8245*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8246*9880d681SAndroid Build Coastguard Worker return true;
8247*9880d681SAndroid Build Coastguard Worker }
8248*9880d681SAndroid Build Coastguard Worker case ARM::t2LDMIA_UPD: {
8249*9880d681SAndroid Build Coastguard Worker // If this is a load of a single register, then we should use
8250*9880d681SAndroid Build Coastguard Worker // a post-indexed LDR instruction instead, per the ARM ARM.
8251*9880d681SAndroid Build Coastguard Worker if (Inst.getNumOperands() != 5)
8252*9880d681SAndroid Build Coastguard Worker return false;
8253*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8254*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::t2LDR_POST);
8255*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rt
8256*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
8257*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8258*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(4));
8259*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // CondCode
8260*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8261*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8262*9880d681SAndroid Build Coastguard Worker return true;
8263*9880d681SAndroid Build Coastguard Worker }
8264*9880d681SAndroid Build Coastguard Worker case ARM::t2STMDB_UPD: {
8265*9880d681SAndroid Build Coastguard Worker // If this is a store of a single register, then we should use
8266*9880d681SAndroid Build Coastguard Worker // a pre-indexed STR instruction instead, per the ARM ARM.
8267*9880d681SAndroid Build Coastguard Worker if (Inst.getNumOperands() != 5)
8268*9880d681SAndroid Build Coastguard Worker return false;
8269*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8270*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::t2STR_PRE);
8271*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
8272*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rt
8273*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8274*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(-4));
8275*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // CondCode
8276*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8277*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8278*9880d681SAndroid Build Coastguard Worker return true;
8279*9880d681SAndroid Build Coastguard Worker }
8280*9880d681SAndroid Build Coastguard Worker case ARM::LDMIA_UPD:
8281*9880d681SAndroid Build Coastguard Worker // If this is a load of a single register via a 'pop', then we should use
8282*9880d681SAndroid Build Coastguard Worker // a post-indexed LDR instruction instead, per the ARM ARM.
8283*9880d681SAndroid Build Coastguard Worker if (static_cast<ARMOperand &>(*Operands[0]).getToken() == "pop" &&
8284*9880d681SAndroid Build Coastguard Worker Inst.getNumOperands() == 5) {
8285*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8286*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::LDR_POST_IMM);
8287*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rt
8288*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
8289*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // Rn
8290*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createReg(0)); // am2offset
8291*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(4));
8292*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // CondCode
8293*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8294*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8295*9880d681SAndroid Build Coastguard Worker return true;
8296*9880d681SAndroid Build Coastguard Worker }
8297*9880d681SAndroid Build Coastguard Worker break;
8298*9880d681SAndroid Build Coastguard Worker case ARM::STMDB_UPD:
8299*9880d681SAndroid Build Coastguard Worker // If this is a store of a single register via a 'push', then we should use
8300*9880d681SAndroid Build Coastguard Worker // a pre-indexed STR instruction instead, per the ARM ARM.
8301*9880d681SAndroid Build Coastguard Worker if (static_cast<ARMOperand &>(*Operands[0]).getToken() == "push" &&
8302*9880d681SAndroid Build Coastguard Worker Inst.getNumOperands() == 5) {
8303*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8304*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::STR_PRE_IMM);
8305*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
8306*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4)); // Rt
8307*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
8308*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(MCOperand::createImm(-4));
8309*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2)); // CondCode
8310*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8311*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8312*9880d681SAndroid Build Coastguard Worker }
8313*9880d681SAndroid Build Coastguard Worker break;
8314*9880d681SAndroid Build Coastguard Worker case ARM::t2ADDri12:
8315*9880d681SAndroid Build Coastguard Worker // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
8316*9880d681SAndroid Build Coastguard Worker // mnemonic was used (not "addw"), encoding T3 is preferred.
8317*9880d681SAndroid Build Coastguard Worker if (static_cast<ARMOperand &>(*Operands[0]).getToken() != "add" ||
8318*9880d681SAndroid Build Coastguard Worker ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
8319*9880d681SAndroid Build Coastguard Worker break;
8320*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2ADDri);
8321*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(0)); // cc_out
8322*9880d681SAndroid Build Coastguard Worker break;
8323*9880d681SAndroid Build Coastguard Worker case ARM::t2SUBri12:
8324*9880d681SAndroid Build Coastguard Worker // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
8325*9880d681SAndroid Build Coastguard Worker // mnemonic was used (not "subw"), encoding T3 is preferred.
8326*9880d681SAndroid Build Coastguard Worker if (static_cast<ARMOperand &>(*Operands[0]).getToken() != "sub" ||
8327*9880d681SAndroid Build Coastguard Worker ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
8328*9880d681SAndroid Build Coastguard Worker break;
8329*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2SUBri);
8330*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(0)); // cc_out
8331*9880d681SAndroid Build Coastguard Worker break;
8332*9880d681SAndroid Build Coastguard Worker case ARM::tADDi8:
8333*9880d681SAndroid Build Coastguard Worker // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
8334*9880d681SAndroid Build Coastguard Worker // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
8335*9880d681SAndroid Build Coastguard Worker // to encoding T2 if <Rd> is specified and encoding T2 is preferred
8336*9880d681SAndroid Build Coastguard Worker // to encoding T1 if <Rd> is omitted."
8337*9880d681SAndroid Build Coastguard Worker if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
8338*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::tADDi3);
8339*9880d681SAndroid Build Coastguard Worker return true;
8340*9880d681SAndroid Build Coastguard Worker }
8341*9880d681SAndroid Build Coastguard Worker break;
8342*9880d681SAndroid Build Coastguard Worker case ARM::tSUBi8:
8343*9880d681SAndroid Build Coastguard Worker // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
8344*9880d681SAndroid Build Coastguard Worker // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
8345*9880d681SAndroid Build Coastguard Worker // to encoding T2 if <Rd> is specified and encoding T2 is preferred
8346*9880d681SAndroid Build Coastguard Worker // to encoding T1 if <Rd> is omitted."
8347*9880d681SAndroid Build Coastguard Worker if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
8348*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::tSUBi3);
8349*9880d681SAndroid Build Coastguard Worker return true;
8350*9880d681SAndroid Build Coastguard Worker }
8351*9880d681SAndroid Build Coastguard Worker break;
8352*9880d681SAndroid Build Coastguard Worker case ARM::t2ADDri:
8353*9880d681SAndroid Build Coastguard Worker case ARM::t2SUBri: {
8354*9880d681SAndroid Build Coastguard Worker // If the destination and first source operand are the same, and
8355*9880d681SAndroid Build Coastguard Worker // the flags are compatible with the current IT status, use encoding T2
8356*9880d681SAndroid Build Coastguard Worker // instead of T3. For compatibility with the system 'as'. Make sure the
8357*9880d681SAndroid Build Coastguard Worker // wide encoding wasn't explicit.
8358*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
8359*9880d681SAndroid Build Coastguard Worker !isARMLowRegister(Inst.getOperand(0).getReg()) ||
8360*9880d681SAndroid Build Coastguard Worker (unsigned)Inst.getOperand(2).getImm() > 255 ||
8361*9880d681SAndroid Build Coastguard Worker ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
8362*9880d681SAndroid Build Coastguard Worker (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
8363*9880d681SAndroid Build Coastguard Worker (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
8364*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).getToken() == ".w"))
8365*9880d681SAndroid Build Coastguard Worker break;
8366*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8367*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
8368*9880d681SAndroid Build Coastguard Worker ARM::tADDi8 : ARM::tSUBi8);
8369*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8370*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
8371*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8372*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
8373*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8374*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8375*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8376*9880d681SAndroid Build Coastguard Worker return true;
8377*9880d681SAndroid Build Coastguard Worker }
8378*9880d681SAndroid Build Coastguard Worker case ARM::t2ADDrr: {
8379*9880d681SAndroid Build Coastguard Worker // If the destination and first source operand are the same, and
8380*9880d681SAndroid Build Coastguard Worker // there's no setting of the flags, use encoding T2 instead of T3.
8381*9880d681SAndroid Build Coastguard Worker // Note that this is only for ADD, not SUB. This mirrors the system
8382*9880d681SAndroid Build Coastguard Worker // 'as' behaviour. Also take advantage of ADD being commutative.
8383*9880d681SAndroid Build Coastguard Worker // Make sure the wide encoding wasn't explicit.
8384*9880d681SAndroid Build Coastguard Worker bool Swap = false;
8385*9880d681SAndroid Build Coastguard Worker auto DestReg = Inst.getOperand(0).getReg();
8386*9880d681SAndroid Build Coastguard Worker bool Transform = DestReg == Inst.getOperand(1).getReg();
8387*9880d681SAndroid Build Coastguard Worker if (!Transform && DestReg == Inst.getOperand(2).getReg()) {
8388*9880d681SAndroid Build Coastguard Worker Transform = true;
8389*9880d681SAndroid Build Coastguard Worker Swap = true;
8390*9880d681SAndroid Build Coastguard Worker }
8391*9880d681SAndroid Build Coastguard Worker if (!Transform ||
8392*9880d681SAndroid Build Coastguard Worker Inst.getOperand(5).getReg() != 0 ||
8393*9880d681SAndroid Build Coastguard Worker (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
8394*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).getToken() == ".w"))
8395*9880d681SAndroid Build Coastguard Worker break;
8396*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8397*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::tADDhirr);
8398*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8399*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8400*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(Swap ? 1 : 2));
8401*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8402*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8403*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8404*9880d681SAndroid Build Coastguard Worker return true;
8405*9880d681SAndroid Build Coastguard Worker }
8406*9880d681SAndroid Build Coastguard Worker case ARM::tADDrSP: {
8407*9880d681SAndroid Build Coastguard Worker // If the non-SP source operand and the destination operand are not the
8408*9880d681SAndroid Build Coastguard Worker // same, we need to use the 32-bit encoding if it's available.
8409*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
8410*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2ADDrr);
8411*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(0)); // cc_out
8412*9880d681SAndroid Build Coastguard Worker return true;
8413*9880d681SAndroid Build Coastguard Worker }
8414*9880d681SAndroid Build Coastguard Worker break;
8415*9880d681SAndroid Build Coastguard Worker }
8416*9880d681SAndroid Build Coastguard Worker case ARM::tB:
8417*9880d681SAndroid Build Coastguard Worker // A Thumb conditional branch outside of an IT block is a tBcc.
8418*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
8419*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::tBcc);
8420*9880d681SAndroid Build Coastguard Worker return true;
8421*9880d681SAndroid Build Coastguard Worker }
8422*9880d681SAndroid Build Coastguard Worker break;
8423*9880d681SAndroid Build Coastguard Worker case ARM::t2B:
8424*9880d681SAndroid Build Coastguard Worker // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
8425*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
8426*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2Bcc);
8427*9880d681SAndroid Build Coastguard Worker return true;
8428*9880d681SAndroid Build Coastguard Worker }
8429*9880d681SAndroid Build Coastguard Worker break;
8430*9880d681SAndroid Build Coastguard Worker case ARM::t2Bcc:
8431*9880d681SAndroid Build Coastguard Worker // If the conditional is AL or we're in an IT block, we really want t2B.
8432*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
8433*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2B);
8434*9880d681SAndroid Build Coastguard Worker return true;
8435*9880d681SAndroid Build Coastguard Worker }
8436*9880d681SAndroid Build Coastguard Worker break;
8437*9880d681SAndroid Build Coastguard Worker case ARM::tBcc:
8438*9880d681SAndroid Build Coastguard Worker // If the conditional is AL, we really want tB.
8439*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(1).getImm() == ARMCC::AL) {
8440*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::tB);
8441*9880d681SAndroid Build Coastguard Worker return true;
8442*9880d681SAndroid Build Coastguard Worker }
8443*9880d681SAndroid Build Coastguard Worker break;
8444*9880d681SAndroid Build Coastguard Worker case ARM::tLDMIA: {
8445*9880d681SAndroid Build Coastguard Worker // If the register list contains any high registers, or if the writeback
8446*9880d681SAndroid Build Coastguard Worker // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
8447*9880d681SAndroid Build Coastguard Worker // instead if we're in Thumb2. Otherwise, this should have generated
8448*9880d681SAndroid Build Coastguard Worker // an error in validateInstruction().
8449*9880d681SAndroid Build Coastguard Worker unsigned Rn = Inst.getOperand(0).getReg();
8450*9880d681SAndroid Build Coastguard Worker bool hasWritebackToken =
8451*9880d681SAndroid Build Coastguard Worker (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
8452*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[3]).getToken() == "!");
8453*9880d681SAndroid Build Coastguard Worker bool listContainsBase;
8454*9880d681SAndroid Build Coastguard Worker if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
8455*9880d681SAndroid Build Coastguard Worker (!listContainsBase && !hasWritebackToken) ||
8456*9880d681SAndroid Build Coastguard Worker (listContainsBase && hasWritebackToken)) {
8457*9880d681SAndroid Build Coastguard Worker // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
8458*9880d681SAndroid Build Coastguard Worker assert (isThumbTwo());
8459*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
8460*9880d681SAndroid Build Coastguard Worker // If we're switching to the updating version, we need to insert
8461*9880d681SAndroid Build Coastguard Worker // the writeback tied operand.
8462*9880d681SAndroid Build Coastguard Worker if (hasWritebackToken)
8463*9880d681SAndroid Build Coastguard Worker Inst.insert(Inst.begin(),
8464*9880d681SAndroid Build Coastguard Worker MCOperand::createReg(Inst.getOperand(0).getReg()));
8465*9880d681SAndroid Build Coastguard Worker return true;
8466*9880d681SAndroid Build Coastguard Worker }
8467*9880d681SAndroid Build Coastguard Worker break;
8468*9880d681SAndroid Build Coastguard Worker }
8469*9880d681SAndroid Build Coastguard Worker case ARM::tSTMIA_UPD: {
8470*9880d681SAndroid Build Coastguard Worker // If the register list contains any high registers, we need to use
8471*9880d681SAndroid Build Coastguard Worker // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
8472*9880d681SAndroid Build Coastguard Worker // should have generated an error in validateInstruction().
8473*9880d681SAndroid Build Coastguard Worker unsigned Rn = Inst.getOperand(0).getReg();
8474*9880d681SAndroid Build Coastguard Worker bool listContainsBase;
8475*9880d681SAndroid Build Coastguard Worker if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
8476*9880d681SAndroid Build Coastguard Worker // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
8477*9880d681SAndroid Build Coastguard Worker assert (isThumbTwo());
8478*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2STMIA_UPD);
8479*9880d681SAndroid Build Coastguard Worker return true;
8480*9880d681SAndroid Build Coastguard Worker }
8481*9880d681SAndroid Build Coastguard Worker break;
8482*9880d681SAndroid Build Coastguard Worker }
8483*9880d681SAndroid Build Coastguard Worker case ARM::tPOP: {
8484*9880d681SAndroid Build Coastguard Worker bool listContainsBase;
8485*9880d681SAndroid Build Coastguard Worker // If the register list contains any high registers, we need to use
8486*9880d681SAndroid Build Coastguard Worker // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
8487*9880d681SAndroid Build Coastguard Worker // should have generated an error in validateInstruction().
8488*9880d681SAndroid Build Coastguard Worker if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
8489*9880d681SAndroid Build Coastguard Worker return false;
8490*9880d681SAndroid Build Coastguard Worker assert (isThumbTwo());
8491*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2LDMIA_UPD);
8492*9880d681SAndroid Build Coastguard Worker // Add the base register and writeback operands.
8493*9880d681SAndroid Build Coastguard Worker Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP));
8494*9880d681SAndroid Build Coastguard Worker Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP));
8495*9880d681SAndroid Build Coastguard Worker return true;
8496*9880d681SAndroid Build Coastguard Worker }
8497*9880d681SAndroid Build Coastguard Worker case ARM::tPUSH: {
8498*9880d681SAndroid Build Coastguard Worker bool listContainsBase;
8499*9880d681SAndroid Build Coastguard Worker if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
8500*9880d681SAndroid Build Coastguard Worker return false;
8501*9880d681SAndroid Build Coastguard Worker assert (isThumbTwo());
8502*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(ARM::t2STMDB_UPD);
8503*9880d681SAndroid Build Coastguard Worker // Add the base register and writeback operands.
8504*9880d681SAndroid Build Coastguard Worker Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP));
8505*9880d681SAndroid Build Coastguard Worker Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP));
8506*9880d681SAndroid Build Coastguard Worker return true;
8507*9880d681SAndroid Build Coastguard Worker }
8508*9880d681SAndroid Build Coastguard Worker case ARM::t2MOVi: {
8509*9880d681SAndroid Build Coastguard Worker // If we can use the 16-bit encoding and the user didn't explicitly
8510*9880d681SAndroid Build Coastguard Worker // request the 32-bit variant, transform it here.
8511*9880d681SAndroid Build Coastguard Worker if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
8512*9880d681SAndroid Build Coastguard Worker (unsigned)Inst.getOperand(1).getImm() <= 255 &&
8513*9880d681SAndroid Build Coastguard Worker ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
8514*9880d681SAndroid Build Coastguard Worker Inst.getOperand(4).getReg() == ARM::CPSR) ||
8515*9880d681SAndroid Build Coastguard Worker (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
8516*9880d681SAndroid Build Coastguard Worker (!static_cast<ARMOperand &>(*Operands[2]).isToken() ||
8517*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[2]).getToken() != ".w")) {
8518*9880d681SAndroid Build Coastguard Worker // The operands aren't in the same order for tMOVi8...
8519*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8520*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::tMOVi8);
8521*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8522*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8523*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
8524*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
8525*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8526*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8527*9880d681SAndroid Build Coastguard Worker return true;
8528*9880d681SAndroid Build Coastguard Worker }
8529*9880d681SAndroid Build Coastguard Worker break;
8530*9880d681SAndroid Build Coastguard Worker }
8531*9880d681SAndroid Build Coastguard Worker case ARM::t2MOVr: {
8532*9880d681SAndroid Build Coastguard Worker // If we can use the 16-bit encoding and the user didn't explicitly
8533*9880d681SAndroid Build Coastguard Worker // request the 32-bit variant, transform it here.
8534*9880d681SAndroid Build Coastguard Worker if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
8535*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(1).getReg()) &&
8536*9880d681SAndroid Build Coastguard Worker Inst.getOperand(2).getImm() == ARMCC::AL &&
8537*9880d681SAndroid Build Coastguard Worker Inst.getOperand(4).getReg() == ARM::CPSR &&
8538*9880d681SAndroid Build Coastguard Worker (!static_cast<ARMOperand &>(*Operands[2]).isToken() ||
8539*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[2]).getToken() != ".w")) {
8540*9880d681SAndroid Build Coastguard Worker // The operands aren't the same for tMOV[S]r... (no cc_out)
8541*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8542*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
8543*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8544*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
8545*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
8546*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8547*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8548*9880d681SAndroid Build Coastguard Worker return true;
8549*9880d681SAndroid Build Coastguard Worker }
8550*9880d681SAndroid Build Coastguard Worker break;
8551*9880d681SAndroid Build Coastguard Worker }
8552*9880d681SAndroid Build Coastguard Worker case ARM::t2SXTH:
8553*9880d681SAndroid Build Coastguard Worker case ARM::t2SXTB:
8554*9880d681SAndroid Build Coastguard Worker case ARM::t2UXTH:
8555*9880d681SAndroid Build Coastguard Worker case ARM::t2UXTB: {
8556*9880d681SAndroid Build Coastguard Worker // If we can use the 16-bit encoding and the user didn't explicitly
8557*9880d681SAndroid Build Coastguard Worker // request the 32-bit variant, transform it here.
8558*9880d681SAndroid Build Coastguard Worker if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
8559*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(1).getReg()) &&
8560*9880d681SAndroid Build Coastguard Worker Inst.getOperand(2).getImm() == 0 &&
8561*9880d681SAndroid Build Coastguard Worker (!static_cast<ARMOperand &>(*Operands[2]).isToken() ||
8562*9880d681SAndroid Build Coastguard Worker static_cast<ARMOperand &>(*Operands[2]).getToken() != ".w")) {
8563*9880d681SAndroid Build Coastguard Worker unsigned NewOpc;
8564*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
8565*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Illegal opcode!");
8566*9880d681SAndroid Build Coastguard Worker case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
8567*9880d681SAndroid Build Coastguard Worker case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
8568*9880d681SAndroid Build Coastguard Worker case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
8569*9880d681SAndroid Build Coastguard Worker case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
8570*9880d681SAndroid Build Coastguard Worker }
8571*9880d681SAndroid Build Coastguard Worker // The operands aren't the same for thumb1 (no rotate operand).
8572*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8573*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(NewOpc);
8574*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8575*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
8576*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8577*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8578*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8579*9880d681SAndroid Build Coastguard Worker return true;
8580*9880d681SAndroid Build Coastguard Worker }
8581*9880d681SAndroid Build Coastguard Worker break;
8582*9880d681SAndroid Build Coastguard Worker }
8583*9880d681SAndroid Build Coastguard Worker case ARM::MOVsi: {
8584*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
8585*9880d681SAndroid Build Coastguard Worker // rrx shifts and asr/lsr of #32 is encoded as 0
8586*9880d681SAndroid Build Coastguard Worker if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr)
8587*9880d681SAndroid Build Coastguard Worker return false;
8588*9880d681SAndroid Build Coastguard Worker if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
8589*9880d681SAndroid Build Coastguard Worker // Shifting by zero is accepted as a vanilla 'MOVr'
8590*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8591*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(ARM::MOVr);
8592*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8593*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
8594*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8595*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8596*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
8597*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8598*9880d681SAndroid Build Coastguard Worker return true;
8599*9880d681SAndroid Build Coastguard Worker }
8600*9880d681SAndroid Build Coastguard Worker return false;
8601*9880d681SAndroid Build Coastguard Worker }
8602*9880d681SAndroid Build Coastguard Worker case ARM::ANDrsi:
8603*9880d681SAndroid Build Coastguard Worker case ARM::ORRrsi:
8604*9880d681SAndroid Build Coastguard Worker case ARM::EORrsi:
8605*9880d681SAndroid Build Coastguard Worker case ARM::BICrsi:
8606*9880d681SAndroid Build Coastguard Worker case ARM::SUBrsi:
8607*9880d681SAndroid Build Coastguard Worker case ARM::ADDrsi: {
8608*9880d681SAndroid Build Coastguard Worker unsigned newOpc;
8609*9880d681SAndroid Build Coastguard Worker ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
8610*9880d681SAndroid Build Coastguard Worker if (SOpc == ARM_AM::rrx) return false;
8611*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
8612*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode!");
8613*9880d681SAndroid Build Coastguard Worker case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
8614*9880d681SAndroid Build Coastguard Worker case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
8615*9880d681SAndroid Build Coastguard Worker case ARM::EORrsi: newOpc = ARM::EORrr; break;
8616*9880d681SAndroid Build Coastguard Worker case ARM::BICrsi: newOpc = ARM::BICrr; break;
8617*9880d681SAndroid Build Coastguard Worker case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
8618*9880d681SAndroid Build Coastguard Worker case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
8619*9880d681SAndroid Build Coastguard Worker }
8620*9880d681SAndroid Build Coastguard Worker // If the shift is by zero, use the non-shifted instruction definition.
8621*9880d681SAndroid Build Coastguard Worker // The exception is for right shifts, where 0 == 32
8622*9880d681SAndroid Build Coastguard Worker if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0 &&
8623*9880d681SAndroid Build Coastguard Worker !(SOpc == ARM_AM::lsr || SOpc == ARM_AM::asr)) {
8624*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8625*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(newOpc);
8626*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8627*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
8628*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
8629*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8630*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
8631*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(6));
8632*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8633*9880d681SAndroid Build Coastguard Worker return true;
8634*9880d681SAndroid Build Coastguard Worker }
8635*9880d681SAndroid Build Coastguard Worker return false;
8636*9880d681SAndroid Build Coastguard Worker }
8637*9880d681SAndroid Build Coastguard Worker case ARM::ITasm:
8638*9880d681SAndroid Build Coastguard Worker case ARM::t2IT: {
8639*9880d681SAndroid Build Coastguard Worker // The mask bits for all but the first condition are represented as
8640*9880d681SAndroid Build Coastguard Worker // the low bit of the condition code value implies 't'. We currently
8641*9880d681SAndroid Build Coastguard Worker // always have 1 implies 't', so XOR toggle the bits if the low bit
8642*9880d681SAndroid Build Coastguard Worker // of the condition code is zero.
8643*9880d681SAndroid Build Coastguard Worker MCOperand &MO = Inst.getOperand(1);
8644*9880d681SAndroid Build Coastguard Worker unsigned Mask = MO.getImm();
8645*9880d681SAndroid Build Coastguard Worker unsigned OrigMask = Mask;
8646*9880d681SAndroid Build Coastguard Worker unsigned TZ = countTrailingZeros(Mask);
8647*9880d681SAndroid Build Coastguard Worker if ((Inst.getOperand(0).getImm() & 1) == 0) {
8648*9880d681SAndroid Build Coastguard Worker assert(Mask && TZ <= 3 && "illegal IT mask value!");
8649*9880d681SAndroid Build Coastguard Worker Mask ^= (0xE << TZ) & 0xF;
8650*9880d681SAndroid Build Coastguard Worker }
8651*9880d681SAndroid Build Coastguard Worker MO.setImm(Mask);
8652*9880d681SAndroid Build Coastguard Worker
8653*9880d681SAndroid Build Coastguard Worker // Set up the IT block state according to the IT instruction we just
8654*9880d681SAndroid Build Coastguard Worker // matched.
8655*9880d681SAndroid Build Coastguard Worker assert(!inITBlock() && "nested IT blocks?!");
8656*9880d681SAndroid Build Coastguard Worker ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
8657*9880d681SAndroid Build Coastguard Worker ITState.Mask = OrigMask; // Use the original mask, not the updated one.
8658*9880d681SAndroid Build Coastguard Worker ITState.CurPosition = 0;
8659*9880d681SAndroid Build Coastguard Worker ITState.FirstCond = true;
8660*9880d681SAndroid Build Coastguard Worker break;
8661*9880d681SAndroid Build Coastguard Worker }
8662*9880d681SAndroid Build Coastguard Worker case ARM::t2LSLrr:
8663*9880d681SAndroid Build Coastguard Worker case ARM::t2LSRrr:
8664*9880d681SAndroid Build Coastguard Worker case ARM::t2ASRrr:
8665*9880d681SAndroid Build Coastguard Worker case ARM::t2SBCrr:
8666*9880d681SAndroid Build Coastguard Worker case ARM::t2RORrr:
8667*9880d681SAndroid Build Coastguard Worker case ARM::t2BICrr:
8668*9880d681SAndroid Build Coastguard Worker {
8669*9880d681SAndroid Build Coastguard Worker // Assemblers should use the narrow encodings of these instructions when permissible.
8670*9880d681SAndroid Build Coastguard Worker if ((isARMLowRegister(Inst.getOperand(1).getReg()) &&
8671*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(2).getReg())) &&
8672*9880d681SAndroid Build Coastguard Worker Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
8673*9880d681SAndroid Build Coastguard Worker ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) ||
8674*9880d681SAndroid Build Coastguard Worker (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) &&
8675*9880d681SAndroid Build Coastguard Worker (!static_cast<ARMOperand &>(*Operands[3]).isToken() ||
8676*9880d681SAndroid Build Coastguard Worker !static_cast<ARMOperand &>(*Operands[3]).getToken().equals_lower(
8677*9880d681SAndroid Build Coastguard Worker ".w"))) {
8678*9880d681SAndroid Build Coastguard Worker unsigned NewOpc;
8679*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
8680*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode");
8681*9880d681SAndroid Build Coastguard Worker case ARM::t2LSLrr: NewOpc = ARM::tLSLrr; break;
8682*9880d681SAndroid Build Coastguard Worker case ARM::t2LSRrr: NewOpc = ARM::tLSRrr; break;
8683*9880d681SAndroid Build Coastguard Worker case ARM::t2ASRrr: NewOpc = ARM::tASRrr; break;
8684*9880d681SAndroid Build Coastguard Worker case ARM::t2SBCrr: NewOpc = ARM::tSBC; break;
8685*9880d681SAndroid Build Coastguard Worker case ARM::t2RORrr: NewOpc = ARM::tROR; break;
8686*9880d681SAndroid Build Coastguard Worker case ARM::t2BICrr: NewOpc = ARM::tBIC; break;
8687*9880d681SAndroid Build Coastguard Worker }
8688*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8689*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(NewOpc);
8690*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8691*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
8692*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
8693*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
8694*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8695*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8696*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8697*9880d681SAndroid Build Coastguard Worker return true;
8698*9880d681SAndroid Build Coastguard Worker }
8699*9880d681SAndroid Build Coastguard Worker return false;
8700*9880d681SAndroid Build Coastguard Worker }
8701*9880d681SAndroid Build Coastguard Worker case ARM::t2ANDrr:
8702*9880d681SAndroid Build Coastguard Worker case ARM::t2EORrr:
8703*9880d681SAndroid Build Coastguard Worker case ARM::t2ADCrr:
8704*9880d681SAndroid Build Coastguard Worker case ARM::t2ORRrr:
8705*9880d681SAndroid Build Coastguard Worker {
8706*9880d681SAndroid Build Coastguard Worker // Assemblers should use the narrow encodings of these instructions when permissible.
8707*9880d681SAndroid Build Coastguard Worker // These instructions are special in that they are commutable, so shorter encodings
8708*9880d681SAndroid Build Coastguard Worker // are available more often.
8709*9880d681SAndroid Build Coastguard Worker if ((isARMLowRegister(Inst.getOperand(1).getReg()) &&
8710*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(2).getReg())) &&
8711*9880d681SAndroid Build Coastguard Worker (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() ||
8712*9880d681SAndroid Build Coastguard Worker Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) &&
8713*9880d681SAndroid Build Coastguard Worker ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) ||
8714*9880d681SAndroid Build Coastguard Worker (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) &&
8715*9880d681SAndroid Build Coastguard Worker (!static_cast<ARMOperand &>(*Operands[3]).isToken() ||
8716*9880d681SAndroid Build Coastguard Worker !static_cast<ARMOperand &>(*Operands[3]).getToken().equals_lower(
8717*9880d681SAndroid Build Coastguard Worker ".w"))) {
8718*9880d681SAndroid Build Coastguard Worker unsigned NewOpc;
8719*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
8720*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unexpected opcode");
8721*9880d681SAndroid Build Coastguard Worker case ARM::t2ADCrr: NewOpc = ARM::tADC; break;
8722*9880d681SAndroid Build Coastguard Worker case ARM::t2ANDrr: NewOpc = ARM::tAND; break;
8723*9880d681SAndroid Build Coastguard Worker case ARM::t2EORrr: NewOpc = ARM::tEOR; break;
8724*9880d681SAndroid Build Coastguard Worker case ARM::t2ORRrr: NewOpc = ARM::tORR; break;
8725*9880d681SAndroid Build Coastguard Worker }
8726*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
8727*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(NewOpc);
8728*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(0));
8729*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(5));
8730*9880d681SAndroid Build Coastguard Worker if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) {
8731*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
8732*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
8733*9880d681SAndroid Build Coastguard Worker } else {
8734*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(2));
8735*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(1));
8736*9880d681SAndroid Build Coastguard Worker }
8737*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(3));
8738*9880d681SAndroid Build Coastguard Worker TmpInst.addOperand(Inst.getOperand(4));
8739*9880d681SAndroid Build Coastguard Worker Inst = TmpInst;
8740*9880d681SAndroid Build Coastguard Worker return true;
8741*9880d681SAndroid Build Coastguard Worker }
8742*9880d681SAndroid Build Coastguard Worker return false;
8743*9880d681SAndroid Build Coastguard Worker }
8744*9880d681SAndroid Build Coastguard Worker }
8745*9880d681SAndroid Build Coastguard Worker return false;
8746*9880d681SAndroid Build Coastguard Worker }
8747*9880d681SAndroid Build Coastguard Worker
checkTargetMatchPredicate(MCInst & Inst)8748*9880d681SAndroid Build Coastguard Worker unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
8749*9880d681SAndroid Build Coastguard Worker // 16-bit thumb arithmetic instructions either require or preclude the 'S'
8750*9880d681SAndroid Build Coastguard Worker // suffix depending on whether they're in an IT block or not.
8751*9880d681SAndroid Build Coastguard Worker unsigned Opc = Inst.getOpcode();
8752*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &MCID = MII.get(Opc);
8753*9880d681SAndroid Build Coastguard Worker if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
8754*9880d681SAndroid Build Coastguard Worker assert(MCID.hasOptionalDef() &&
8755*9880d681SAndroid Build Coastguard Worker "optionally flag setting instruction missing optional def operand");
8756*9880d681SAndroid Build Coastguard Worker assert(MCID.NumOperands == Inst.getNumOperands() &&
8757*9880d681SAndroid Build Coastguard Worker "operand count mismatch!");
8758*9880d681SAndroid Build Coastguard Worker // Find the optional-def operand (cc_out).
8759*9880d681SAndroid Build Coastguard Worker unsigned OpNo;
8760*9880d681SAndroid Build Coastguard Worker for (OpNo = 0;
8761*9880d681SAndroid Build Coastguard Worker !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
8762*9880d681SAndroid Build Coastguard Worker ++OpNo)
8763*9880d681SAndroid Build Coastguard Worker ;
8764*9880d681SAndroid Build Coastguard Worker // If we're parsing Thumb1, reject it completely.
8765*9880d681SAndroid Build Coastguard Worker if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
8766*9880d681SAndroid Build Coastguard Worker return Match_MnemonicFail;
8767*9880d681SAndroid Build Coastguard Worker // If we're parsing Thumb2, which form is legal depends on whether we're
8768*9880d681SAndroid Build Coastguard Worker // in an IT block.
8769*9880d681SAndroid Build Coastguard Worker if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
8770*9880d681SAndroid Build Coastguard Worker !inITBlock())
8771*9880d681SAndroid Build Coastguard Worker return Match_RequiresITBlock;
8772*9880d681SAndroid Build Coastguard Worker if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
8773*9880d681SAndroid Build Coastguard Worker inITBlock())
8774*9880d681SAndroid Build Coastguard Worker return Match_RequiresNotITBlock;
8775*9880d681SAndroid Build Coastguard Worker } else if (isThumbOne()) {
8776*9880d681SAndroid Build Coastguard Worker // Some high-register supporting Thumb1 encodings only allow both registers
8777*9880d681SAndroid Build Coastguard Worker // to be from r0-r7 when in Thumb2.
8778*9880d681SAndroid Build Coastguard Worker if (Opc == ARM::tADDhirr && !hasV6MOps() &&
8779*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(1).getReg()) &&
8780*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(2).getReg()))
8781*9880d681SAndroid Build Coastguard Worker return Match_RequiresThumb2;
8782*9880d681SAndroid Build Coastguard Worker // Others only require ARMv6 or later.
8783*9880d681SAndroid Build Coastguard Worker else if (Opc == ARM::tMOVr && !hasV6Ops() &&
8784*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(0).getReg()) &&
8785*9880d681SAndroid Build Coastguard Worker isARMLowRegister(Inst.getOperand(1).getReg()))
8786*9880d681SAndroid Build Coastguard Worker return Match_RequiresV6;
8787*9880d681SAndroid Build Coastguard Worker }
8788*9880d681SAndroid Build Coastguard Worker
8789*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0; I < MCID.NumOperands; ++I)
8790*9880d681SAndroid Build Coastguard Worker if (MCID.OpInfo[I].RegClass == ARM::rGPRRegClassID) {
8791*9880d681SAndroid Build Coastguard Worker // rGPRRegClass excludes PC, and also excluded SP before ARMv8
8792*9880d681SAndroid Build Coastguard Worker if ((Inst.getOperand(I).getReg() == ARM::SP) && !hasV8Ops())
8793*9880d681SAndroid Build Coastguard Worker return Match_RequiresV8;
8794*9880d681SAndroid Build Coastguard Worker else if (Inst.getOperand(I).getReg() == ARM::PC)
8795*9880d681SAndroid Build Coastguard Worker return Match_InvalidOperand;
8796*9880d681SAndroid Build Coastguard Worker }
8797*9880d681SAndroid Build Coastguard Worker
8798*9880d681SAndroid Build Coastguard Worker return Match_Success;
8799*9880d681SAndroid Build Coastguard Worker }
8800*9880d681SAndroid Build Coastguard Worker
8801*9880d681SAndroid Build Coastguard Worker namespace llvm {
IsCPSRDead(MCInst * Instr)8802*9880d681SAndroid Build Coastguard Worker template <> inline bool IsCPSRDead<MCInst>(MCInst *Instr) {
8803*9880d681SAndroid Build Coastguard Worker return true; // In an assembly source, no need to second-guess
8804*9880d681SAndroid Build Coastguard Worker }
8805*9880d681SAndroid Build Coastguard Worker }
8806*9880d681SAndroid Build Coastguard Worker
8807*9880d681SAndroid Build Coastguard Worker static const char *getSubtargetFeatureName(uint64_t Val);
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)8808*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
8809*9880d681SAndroid Build Coastguard Worker OperandVector &Operands,
8810*9880d681SAndroid Build Coastguard Worker MCStreamer &Out, uint64_t &ErrorInfo,
8811*9880d681SAndroid Build Coastguard Worker bool MatchingInlineAsm) {
8812*9880d681SAndroid Build Coastguard Worker MCInst Inst;
8813*9880d681SAndroid Build Coastguard Worker unsigned MatchResult;
8814*9880d681SAndroid Build Coastguard Worker
8815*9880d681SAndroid Build Coastguard Worker MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
8816*9880d681SAndroid Build Coastguard Worker MatchingInlineAsm);
8817*9880d681SAndroid Build Coastguard Worker switch (MatchResult) {
8818*9880d681SAndroid Build Coastguard Worker case Match_Success:
8819*9880d681SAndroid Build Coastguard Worker // Context sensitive operand constraints aren't handled by the matcher,
8820*9880d681SAndroid Build Coastguard Worker // so check them here.
8821*9880d681SAndroid Build Coastguard Worker if (validateInstruction(Inst, Operands)) {
8822*9880d681SAndroid Build Coastguard Worker // Still progress the IT block, otherwise one wrong condition causes
8823*9880d681SAndroid Build Coastguard Worker // nasty cascading errors.
8824*9880d681SAndroid Build Coastguard Worker forwardITPosition();
8825*9880d681SAndroid Build Coastguard Worker return true;
8826*9880d681SAndroid Build Coastguard Worker }
8827*9880d681SAndroid Build Coastguard Worker
8828*9880d681SAndroid Build Coastguard Worker { // processInstruction() updates inITBlock state, we need to save it away
8829*9880d681SAndroid Build Coastguard Worker bool wasInITBlock = inITBlock();
8830*9880d681SAndroid Build Coastguard Worker
8831*9880d681SAndroid Build Coastguard Worker // Some instructions need post-processing to, for example, tweak which
8832*9880d681SAndroid Build Coastguard Worker // encoding is selected. Loop on it while changes happen so the
8833*9880d681SAndroid Build Coastguard Worker // individual transformations can chain off each other. E.g.,
8834*9880d681SAndroid Build Coastguard Worker // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
8835*9880d681SAndroid Build Coastguard Worker while (processInstruction(Inst, Operands, Out))
8836*9880d681SAndroid Build Coastguard Worker ;
8837*9880d681SAndroid Build Coastguard Worker
8838*9880d681SAndroid Build Coastguard Worker // Only after the instruction is fully processed, we can validate it
8839*9880d681SAndroid Build Coastguard Worker if (wasInITBlock && hasV8Ops() && isThumb() &&
8840*9880d681SAndroid Build Coastguard Worker !isV8EligibleForIT(&Inst)) {
8841*9880d681SAndroid Build Coastguard Worker Warning(IDLoc, "deprecated instruction in IT block");
8842*9880d681SAndroid Build Coastguard Worker }
8843*9880d681SAndroid Build Coastguard Worker }
8844*9880d681SAndroid Build Coastguard Worker
8845*9880d681SAndroid Build Coastguard Worker // Only move forward at the very end so that everything in validate
8846*9880d681SAndroid Build Coastguard Worker // and process gets a consistent answer about whether we're in an IT
8847*9880d681SAndroid Build Coastguard Worker // block.
8848*9880d681SAndroid Build Coastguard Worker forwardITPosition();
8849*9880d681SAndroid Build Coastguard Worker
8850*9880d681SAndroid Build Coastguard Worker // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
8851*9880d681SAndroid Build Coastguard Worker // doesn't actually encode.
8852*9880d681SAndroid Build Coastguard Worker if (Inst.getOpcode() == ARM::ITasm)
8853*9880d681SAndroid Build Coastguard Worker return false;
8854*9880d681SAndroid Build Coastguard Worker
8855*9880d681SAndroid Build Coastguard Worker Inst.setLoc(IDLoc);
8856*9880d681SAndroid Build Coastguard Worker Out.EmitInstruction(Inst, getSTI());
8857*9880d681SAndroid Build Coastguard Worker return false;
8858*9880d681SAndroid Build Coastguard Worker case Match_MissingFeature: {
8859*9880d681SAndroid Build Coastguard Worker assert(ErrorInfo && "Unknown missing feature!");
8860*9880d681SAndroid Build Coastguard Worker // Special case the error message for the very common case where only
8861*9880d681SAndroid Build Coastguard Worker // a single subtarget feature is missing (Thumb vs. ARM, e.g.).
8862*9880d681SAndroid Build Coastguard Worker std::string Msg = "instruction requires:";
8863*9880d681SAndroid Build Coastguard Worker uint64_t Mask = 1;
8864*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
8865*9880d681SAndroid Build Coastguard Worker if (ErrorInfo & Mask) {
8866*9880d681SAndroid Build Coastguard Worker Msg += " ";
8867*9880d681SAndroid Build Coastguard Worker Msg += getSubtargetFeatureName(ErrorInfo & Mask);
8868*9880d681SAndroid Build Coastguard Worker }
8869*9880d681SAndroid Build Coastguard Worker Mask <<= 1;
8870*9880d681SAndroid Build Coastguard Worker }
8871*9880d681SAndroid Build Coastguard Worker return Error(IDLoc, Msg);
8872*9880d681SAndroid Build Coastguard Worker }
8873*9880d681SAndroid Build Coastguard Worker case Match_InvalidOperand: {
8874*9880d681SAndroid Build Coastguard Worker SMLoc ErrorLoc = IDLoc;
8875*9880d681SAndroid Build Coastguard Worker if (ErrorInfo != ~0ULL) {
8876*9880d681SAndroid Build Coastguard Worker if (ErrorInfo >= Operands.size())
8877*9880d681SAndroid Build Coastguard Worker return Error(IDLoc, "too few operands for instruction");
8878*9880d681SAndroid Build Coastguard Worker
8879*9880d681SAndroid Build Coastguard Worker ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc();
8880*9880d681SAndroid Build Coastguard Worker if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
8881*9880d681SAndroid Build Coastguard Worker }
8882*9880d681SAndroid Build Coastguard Worker
8883*9880d681SAndroid Build Coastguard Worker return Error(ErrorLoc, "invalid operand for instruction");
8884*9880d681SAndroid Build Coastguard Worker }
8885*9880d681SAndroid Build Coastguard Worker case Match_MnemonicFail:
8886*9880d681SAndroid Build Coastguard Worker return Error(IDLoc, "invalid instruction",
8887*9880d681SAndroid Build Coastguard Worker ((ARMOperand &)*Operands[0]).getLocRange());
8888*9880d681SAndroid Build Coastguard Worker case Match_RequiresNotITBlock:
8889*9880d681SAndroid Build Coastguard Worker return Error(IDLoc, "flag setting instruction only valid outside IT block");
8890*9880d681SAndroid Build Coastguard Worker case Match_RequiresITBlock:
8891*9880d681SAndroid Build Coastguard Worker return Error(IDLoc, "instruction only valid inside IT block");
8892*9880d681SAndroid Build Coastguard Worker case Match_RequiresV6:
8893*9880d681SAndroid Build Coastguard Worker return Error(IDLoc, "instruction variant requires ARMv6 or later");
8894*9880d681SAndroid Build Coastguard Worker case Match_RequiresThumb2:
8895*9880d681SAndroid Build Coastguard Worker return Error(IDLoc, "instruction variant requires Thumb2");
8896*9880d681SAndroid Build Coastguard Worker case Match_RequiresV8:
8897*9880d681SAndroid Build Coastguard Worker return Error(IDLoc, "instruction variant requires ARMv8 or later");
8898*9880d681SAndroid Build Coastguard Worker case Match_ImmRange0_15: {
8899*9880d681SAndroid Build Coastguard Worker SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc();
8900*9880d681SAndroid Build Coastguard Worker if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
8901*9880d681SAndroid Build Coastguard Worker return Error(ErrorLoc, "immediate operand must be in the range [0,15]");
8902*9880d681SAndroid Build Coastguard Worker }
8903*9880d681SAndroid Build Coastguard Worker case Match_ImmRange0_239: {
8904*9880d681SAndroid Build Coastguard Worker SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc();
8905*9880d681SAndroid Build Coastguard Worker if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
8906*9880d681SAndroid Build Coastguard Worker return Error(ErrorLoc, "immediate operand must be in the range [0,239]");
8907*9880d681SAndroid Build Coastguard Worker }
8908*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequiresNone:
8909*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequiresNone:
8910*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires16:
8911*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequires16:
8912*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires32:
8913*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequires32:
8914*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires64:
8915*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequires64:
8916*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires64or128:
8917*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequires64or128:
8918*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires64or128or256:
8919*9880d681SAndroid Build Coastguard Worker {
8920*9880d681SAndroid Build Coastguard Worker SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getAlignmentLoc();
8921*9880d681SAndroid Build Coastguard Worker if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
8922*9880d681SAndroid Build Coastguard Worker switch (MatchResult) {
8923*9880d681SAndroid Build Coastguard Worker default:
8924*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Missing Match_Aligned type");
8925*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequiresNone:
8926*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequiresNone:
8927*9880d681SAndroid Build Coastguard Worker return Error(ErrorLoc, "alignment must be omitted");
8928*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires16:
8929*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequires16:
8930*9880d681SAndroid Build Coastguard Worker return Error(ErrorLoc, "alignment must be 16 or omitted");
8931*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires32:
8932*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequires32:
8933*9880d681SAndroid Build Coastguard Worker return Error(ErrorLoc, "alignment must be 32 or omitted");
8934*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires64:
8935*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequires64:
8936*9880d681SAndroid Build Coastguard Worker return Error(ErrorLoc, "alignment must be 64 or omitted");
8937*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires64or128:
8938*9880d681SAndroid Build Coastguard Worker case Match_DupAlignedMemoryRequires64or128:
8939*9880d681SAndroid Build Coastguard Worker return Error(ErrorLoc, "alignment must be 64, 128 or omitted");
8940*9880d681SAndroid Build Coastguard Worker case Match_AlignedMemoryRequires64or128or256:
8941*9880d681SAndroid Build Coastguard Worker return Error(ErrorLoc, "alignment must be 64, 128, 256 or omitted");
8942*9880d681SAndroid Build Coastguard Worker }
8943*9880d681SAndroid Build Coastguard Worker }
8944*9880d681SAndroid Build Coastguard Worker }
8945*9880d681SAndroid Build Coastguard Worker
8946*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Implement any new match types added!");
8947*9880d681SAndroid Build Coastguard Worker }
8948*9880d681SAndroid Build Coastguard Worker
8949*9880d681SAndroid Build Coastguard Worker /// parseDirective parses the arm specific directives
ParseDirective(AsmToken DirectiveID)8950*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
8951*9880d681SAndroid Build Coastguard Worker const MCObjectFileInfo::Environment Format =
8952*9880d681SAndroid Build Coastguard Worker getContext().getObjectFileInfo()->getObjectFileType();
8953*9880d681SAndroid Build Coastguard Worker bool IsMachO = Format == MCObjectFileInfo::IsMachO;
8954*9880d681SAndroid Build Coastguard Worker bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
8955*9880d681SAndroid Build Coastguard Worker
8956*9880d681SAndroid Build Coastguard Worker StringRef IDVal = DirectiveID.getIdentifier();
8957*9880d681SAndroid Build Coastguard Worker if (IDVal == ".word")
8958*9880d681SAndroid Build Coastguard Worker return parseLiteralValues(4, DirectiveID.getLoc());
8959*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".short" || IDVal == ".hword")
8960*9880d681SAndroid Build Coastguard Worker return parseLiteralValues(2, DirectiveID.getLoc());
8961*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".thumb")
8962*9880d681SAndroid Build Coastguard Worker return parseDirectiveThumb(DirectiveID.getLoc());
8963*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".arm")
8964*9880d681SAndroid Build Coastguard Worker return parseDirectiveARM(DirectiveID.getLoc());
8965*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".thumb_func")
8966*9880d681SAndroid Build Coastguard Worker return parseDirectiveThumbFunc(DirectiveID.getLoc());
8967*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".code")
8968*9880d681SAndroid Build Coastguard Worker return parseDirectiveCode(DirectiveID.getLoc());
8969*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".syntax")
8970*9880d681SAndroid Build Coastguard Worker return parseDirectiveSyntax(DirectiveID.getLoc());
8971*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".unreq")
8972*9880d681SAndroid Build Coastguard Worker return parseDirectiveUnreq(DirectiveID.getLoc());
8973*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".fnend")
8974*9880d681SAndroid Build Coastguard Worker return parseDirectiveFnEnd(DirectiveID.getLoc());
8975*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".cantunwind")
8976*9880d681SAndroid Build Coastguard Worker return parseDirectiveCantUnwind(DirectiveID.getLoc());
8977*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".personality")
8978*9880d681SAndroid Build Coastguard Worker return parseDirectivePersonality(DirectiveID.getLoc());
8979*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".handlerdata")
8980*9880d681SAndroid Build Coastguard Worker return parseDirectiveHandlerData(DirectiveID.getLoc());
8981*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".setfp")
8982*9880d681SAndroid Build Coastguard Worker return parseDirectiveSetFP(DirectiveID.getLoc());
8983*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".pad")
8984*9880d681SAndroid Build Coastguard Worker return parseDirectivePad(DirectiveID.getLoc());
8985*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".save")
8986*9880d681SAndroid Build Coastguard Worker return parseDirectiveRegSave(DirectiveID.getLoc(), false);
8987*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".vsave")
8988*9880d681SAndroid Build Coastguard Worker return parseDirectiveRegSave(DirectiveID.getLoc(), true);
8989*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".ltorg" || IDVal == ".pool")
8990*9880d681SAndroid Build Coastguard Worker return parseDirectiveLtorg(DirectiveID.getLoc());
8991*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".even")
8992*9880d681SAndroid Build Coastguard Worker return parseDirectiveEven(DirectiveID.getLoc());
8993*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".personalityindex")
8994*9880d681SAndroid Build Coastguard Worker return parseDirectivePersonalityIndex(DirectiveID.getLoc());
8995*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".unwind_raw")
8996*9880d681SAndroid Build Coastguard Worker return parseDirectiveUnwindRaw(DirectiveID.getLoc());
8997*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".movsp")
8998*9880d681SAndroid Build Coastguard Worker return parseDirectiveMovSP(DirectiveID.getLoc());
8999*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".arch_extension")
9000*9880d681SAndroid Build Coastguard Worker return parseDirectiveArchExtension(DirectiveID.getLoc());
9001*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".align")
9002*9880d681SAndroid Build Coastguard Worker return parseDirectiveAlign(DirectiveID.getLoc());
9003*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".thumb_set")
9004*9880d681SAndroid Build Coastguard Worker return parseDirectiveThumbSet(DirectiveID.getLoc());
9005*9880d681SAndroid Build Coastguard Worker
9006*9880d681SAndroid Build Coastguard Worker if (!IsMachO && !IsCOFF) {
9007*9880d681SAndroid Build Coastguard Worker if (IDVal == ".arch")
9008*9880d681SAndroid Build Coastguard Worker return parseDirectiveArch(DirectiveID.getLoc());
9009*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".cpu")
9010*9880d681SAndroid Build Coastguard Worker return parseDirectiveCPU(DirectiveID.getLoc());
9011*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".eabi_attribute")
9012*9880d681SAndroid Build Coastguard Worker return parseDirectiveEabiAttr(DirectiveID.getLoc());
9013*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".fpu")
9014*9880d681SAndroid Build Coastguard Worker return parseDirectiveFPU(DirectiveID.getLoc());
9015*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".fnstart")
9016*9880d681SAndroid Build Coastguard Worker return parseDirectiveFnStart(DirectiveID.getLoc());
9017*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".inst")
9018*9880d681SAndroid Build Coastguard Worker return parseDirectiveInst(DirectiveID.getLoc());
9019*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".inst.n")
9020*9880d681SAndroid Build Coastguard Worker return parseDirectiveInst(DirectiveID.getLoc(), 'n');
9021*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".inst.w")
9022*9880d681SAndroid Build Coastguard Worker return parseDirectiveInst(DirectiveID.getLoc(), 'w');
9023*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".object_arch")
9024*9880d681SAndroid Build Coastguard Worker return parseDirectiveObjectArch(DirectiveID.getLoc());
9025*9880d681SAndroid Build Coastguard Worker else if (IDVal == ".tlsdescseq")
9026*9880d681SAndroid Build Coastguard Worker return parseDirectiveTLSDescSeq(DirectiveID.getLoc());
9027*9880d681SAndroid Build Coastguard Worker }
9028*9880d681SAndroid Build Coastguard Worker
9029*9880d681SAndroid Build Coastguard Worker return true;
9030*9880d681SAndroid Build Coastguard Worker }
9031*9880d681SAndroid Build Coastguard Worker
9032*9880d681SAndroid Build Coastguard Worker /// parseLiteralValues
9033*9880d681SAndroid Build Coastguard Worker /// ::= .hword expression [, expression]*
9034*9880d681SAndroid Build Coastguard Worker /// ::= .short expression [, expression]*
9035*9880d681SAndroid Build Coastguard Worker /// ::= .word expression [, expression]*
parseLiteralValues(unsigned Size,SMLoc L)9036*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseLiteralValues(unsigned Size, SMLoc L) {
9037*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9038*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
9039*9880d681SAndroid Build Coastguard Worker for (;;) {
9040*9880d681SAndroid Build Coastguard Worker const MCExpr *Value;
9041*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Value)) {
9042*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9043*9880d681SAndroid Build Coastguard Worker return false;
9044*9880d681SAndroid Build Coastguard Worker }
9045*9880d681SAndroid Build Coastguard Worker
9046*9880d681SAndroid Build Coastguard Worker getParser().getStreamer().EmitValue(Value, Size, L);
9047*9880d681SAndroid Build Coastguard Worker
9048*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::EndOfStatement))
9049*9880d681SAndroid Build Coastguard Worker break;
9050*9880d681SAndroid Build Coastguard Worker
9051*9880d681SAndroid Build Coastguard Worker // FIXME: Improve diagnostic.
9052*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma)) {
9053*9880d681SAndroid Build Coastguard Worker Error(L, "unexpected token in directive");
9054*9880d681SAndroid Build Coastguard Worker return false;
9055*9880d681SAndroid Build Coastguard Worker }
9056*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9057*9880d681SAndroid Build Coastguard Worker }
9058*9880d681SAndroid Build Coastguard Worker }
9059*9880d681SAndroid Build Coastguard Worker
9060*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9061*9880d681SAndroid Build Coastguard Worker return false;
9062*9880d681SAndroid Build Coastguard Worker }
9063*9880d681SAndroid Build Coastguard Worker
9064*9880d681SAndroid Build Coastguard Worker /// parseDirectiveThumb
9065*9880d681SAndroid Build Coastguard Worker /// ::= .thumb
parseDirectiveThumb(SMLoc L)9066*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
9067*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9068*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
9069*9880d681SAndroid Build Coastguard Worker Error(L, "unexpected token in directive");
9070*9880d681SAndroid Build Coastguard Worker return false;
9071*9880d681SAndroid Build Coastguard Worker }
9072*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9073*9880d681SAndroid Build Coastguard Worker
9074*9880d681SAndroid Build Coastguard Worker if (!hasThumb()) {
9075*9880d681SAndroid Build Coastguard Worker Error(L, "target does not support Thumb mode");
9076*9880d681SAndroid Build Coastguard Worker return false;
9077*9880d681SAndroid Build Coastguard Worker }
9078*9880d681SAndroid Build Coastguard Worker
9079*9880d681SAndroid Build Coastguard Worker if (!isThumb())
9080*9880d681SAndroid Build Coastguard Worker SwitchMode();
9081*9880d681SAndroid Build Coastguard Worker
9082*9880d681SAndroid Build Coastguard Worker getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
9083*9880d681SAndroid Build Coastguard Worker return false;
9084*9880d681SAndroid Build Coastguard Worker }
9085*9880d681SAndroid Build Coastguard Worker
9086*9880d681SAndroid Build Coastguard Worker /// parseDirectiveARM
9087*9880d681SAndroid Build Coastguard Worker /// ::= .arm
parseDirectiveARM(SMLoc L)9088*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
9089*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9090*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
9091*9880d681SAndroid Build Coastguard Worker Error(L, "unexpected token in directive");
9092*9880d681SAndroid Build Coastguard Worker return false;
9093*9880d681SAndroid Build Coastguard Worker }
9094*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9095*9880d681SAndroid Build Coastguard Worker
9096*9880d681SAndroid Build Coastguard Worker if (!hasARM()) {
9097*9880d681SAndroid Build Coastguard Worker Error(L, "target does not support ARM mode");
9098*9880d681SAndroid Build Coastguard Worker return false;
9099*9880d681SAndroid Build Coastguard Worker }
9100*9880d681SAndroid Build Coastguard Worker
9101*9880d681SAndroid Build Coastguard Worker if (isThumb())
9102*9880d681SAndroid Build Coastguard Worker SwitchMode();
9103*9880d681SAndroid Build Coastguard Worker
9104*9880d681SAndroid Build Coastguard Worker getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
9105*9880d681SAndroid Build Coastguard Worker return false;
9106*9880d681SAndroid Build Coastguard Worker }
9107*9880d681SAndroid Build Coastguard Worker
onLabelParsed(MCSymbol * Symbol)9108*9880d681SAndroid Build Coastguard Worker void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) {
9109*9880d681SAndroid Build Coastguard Worker if (NextSymbolIsThumb) {
9110*9880d681SAndroid Build Coastguard Worker getParser().getStreamer().EmitThumbFunc(Symbol);
9111*9880d681SAndroid Build Coastguard Worker NextSymbolIsThumb = false;
9112*9880d681SAndroid Build Coastguard Worker }
9113*9880d681SAndroid Build Coastguard Worker }
9114*9880d681SAndroid Build Coastguard Worker
9115*9880d681SAndroid Build Coastguard Worker /// parseDirectiveThumbFunc
9116*9880d681SAndroid Build Coastguard Worker /// ::= .thumbfunc symbol_name
parseDirectiveThumbFunc(SMLoc L)9117*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
9118*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9119*9880d681SAndroid Build Coastguard Worker const auto Format = getContext().getObjectFileInfo()->getObjectFileType();
9120*9880d681SAndroid Build Coastguard Worker bool IsMachO = Format == MCObjectFileInfo::IsMachO;
9121*9880d681SAndroid Build Coastguard Worker
9122*9880d681SAndroid Build Coastguard Worker // Darwin asm has (optionally) function name after .thumb_func direction
9123*9880d681SAndroid Build Coastguard Worker // ELF doesn't
9124*9880d681SAndroid Build Coastguard Worker if (IsMachO) {
9125*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
9126*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::EndOfStatement)) {
9127*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) {
9128*9880d681SAndroid Build Coastguard Worker Error(L, "unexpected token in .thumb_func directive");
9129*9880d681SAndroid Build Coastguard Worker return false;
9130*9880d681SAndroid Build Coastguard Worker }
9131*9880d681SAndroid Build Coastguard Worker
9132*9880d681SAndroid Build Coastguard Worker MCSymbol *Func =
9133*9880d681SAndroid Build Coastguard Worker getParser().getContext().getOrCreateSymbol(Tok.getIdentifier());
9134*9880d681SAndroid Build Coastguard Worker getParser().getStreamer().EmitThumbFunc(Func);
9135*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Consume the identifier token.
9136*9880d681SAndroid Build Coastguard Worker return false;
9137*9880d681SAndroid Build Coastguard Worker }
9138*9880d681SAndroid Build Coastguard Worker }
9139*9880d681SAndroid Build Coastguard Worker
9140*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
9141*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "unexpected token in directive");
9142*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9143*9880d681SAndroid Build Coastguard Worker return false;
9144*9880d681SAndroid Build Coastguard Worker }
9145*9880d681SAndroid Build Coastguard Worker
9146*9880d681SAndroid Build Coastguard Worker NextSymbolIsThumb = true;
9147*9880d681SAndroid Build Coastguard Worker return false;
9148*9880d681SAndroid Build Coastguard Worker }
9149*9880d681SAndroid Build Coastguard Worker
9150*9880d681SAndroid Build Coastguard Worker /// parseDirectiveSyntax
9151*9880d681SAndroid Build Coastguard Worker /// ::= .syntax unified | divided
parseDirectiveSyntax(SMLoc L)9152*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
9153*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9154*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
9155*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Identifier)) {
9156*9880d681SAndroid Build Coastguard Worker Error(L, "unexpected token in .syntax directive");
9157*9880d681SAndroid Build Coastguard Worker return false;
9158*9880d681SAndroid Build Coastguard Worker }
9159*9880d681SAndroid Build Coastguard Worker
9160*9880d681SAndroid Build Coastguard Worker StringRef Mode = Tok.getString();
9161*9880d681SAndroid Build Coastguard Worker if (Mode == "unified" || Mode == "UNIFIED") {
9162*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9163*9880d681SAndroid Build Coastguard Worker } else if (Mode == "divided" || Mode == "DIVIDED") {
9164*9880d681SAndroid Build Coastguard Worker Error(L, "'.syntax divided' arm asssembly not supported");
9165*9880d681SAndroid Build Coastguard Worker return false;
9166*9880d681SAndroid Build Coastguard Worker } else {
9167*9880d681SAndroid Build Coastguard Worker Error(L, "unrecognized syntax mode in .syntax directive");
9168*9880d681SAndroid Build Coastguard Worker return false;
9169*9880d681SAndroid Build Coastguard Worker }
9170*9880d681SAndroid Build Coastguard Worker
9171*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
9172*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "unexpected token in directive");
9173*9880d681SAndroid Build Coastguard Worker return false;
9174*9880d681SAndroid Build Coastguard Worker }
9175*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9176*9880d681SAndroid Build Coastguard Worker
9177*9880d681SAndroid Build Coastguard Worker // TODO tell the MC streamer the mode
9178*9880d681SAndroid Build Coastguard Worker // getParser().getStreamer().Emit???();
9179*9880d681SAndroid Build Coastguard Worker return false;
9180*9880d681SAndroid Build Coastguard Worker }
9181*9880d681SAndroid Build Coastguard Worker
9182*9880d681SAndroid Build Coastguard Worker /// parseDirectiveCode
9183*9880d681SAndroid Build Coastguard Worker /// ::= .code 16 | 32
parseDirectiveCode(SMLoc L)9184*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
9185*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9186*9880d681SAndroid Build Coastguard Worker const AsmToken &Tok = Parser.getTok();
9187*9880d681SAndroid Build Coastguard Worker if (Tok.isNot(AsmToken::Integer)) {
9188*9880d681SAndroid Build Coastguard Worker Error(L, "unexpected token in .code directive");
9189*9880d681SAndroid Build Coastguard Worker return false;
9190*9880d681SAndroid Build Coastguard Worker }
9191*9880d681SAndroid Build Coastguard Worker int64_t Val = Parser.getTok().getIntVal();
9192*9880d681SAndroid Build Coastguard Worker if (Val != 16 && Val != 32) {
9193*9880d681SAndroid Build Coastguard Worker Error(L, "invalid operand to .code directive");
9194*9880d681SAndroid Build Coastguard Worker return false;
9195*9880d681SAndroid Build Coastguard Worker }
9196*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9197*9880d681SAndroid Build Coastguard Worker
9198*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
9199*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "unexpected token in directive");
9200*9880d681SAndroid Build Coastguard Worker return false;
9201*9880d681SAndroid Build Coastguard Worker }
9202*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9203*9880d681SAndroid Build Coastguard Worker
9204*9880d681SAndroid Build Coastguard Worker if (Val == 16) {
9205*9880d681SAndroid Build Coastguard Worker if (!hasThumb()) {
9206*9880d681SAndroid Build Coastguard Worker Error(L, "target does not support Thumb mode");
9207*9880d681SAndroid Build Coastguard Worker return false;
9208*9880d681SAndroid Build Coastguard Worker }
9209*9880d681SAndroid Build Coastguard Worker
9210*9880d681SAndroid Build Coastguard Worker if (!isThumb())
9211*9880d681SAndroid Build Coastguard Worker SwitchMode();
9212*9880d681SAndroid Build Coastguard Worker getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
9213*9880d681SAndroid Build Coastguard Worker } else {
9214*9880d681SAndroid Build Coastguard Worker if (!hasARM()) {
9215*9880d681SAndroid Build Coastguard Worker Error(L, "target does not support ARM mode");
9216*9880d681SAndroid Build Coastguard Worker return false;
9217*9880d681SAndroid Build Coastguard Worker }
9218*9880d681SAndroid Build Coastguard Worker
9219*9880d681SAndroid Build Coastguard Worker if (isThumb())
9220*9880d681SAndroid Build Coastguard Worker SwitchMode();
9221*9880d681SAndroid Build Coastguard Worker getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
9222*9880d681SAndroid Build Coastguard Worker }
9223*9880d681SAndroid Build Coastguard Worker
9224*9880d681SAndroid Build Coastguard Worker return false;
9225*9880d681SAndroid Build Coastguard Worker }
9226*9880d681SAndroid Build Coastguard Worker
9227*9880d681SAndroid Build Coastguard Worker /// parseDirectiveReq
9228*9880d681SAndroid Build Coastguard Worker /// ::= name .req registername
parseDirectiveReq(StringRef Name,SMLoc L)9229*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
9230*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9231*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the '.req' token.
9232*9880d681SAndroid Build Coastguard Worker unsigned Reg;
9233*9880d681SAndroid Build Coastguard Worker SMLoc SRegLoc, ERegLoc;
9234*9880d681SAndroid Build Coastguard Worker if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
9235*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9236*9880d681SAndroid Build Coastguard Worker Error(SRegLoc, "register name expected");
9237*9880d681SAndroid Build Coastguard Worker return false;
9238*9880d681SAndroid Build Coastguard Worker }
9239*9880d681SAndroid Build Coastguard Worker
9240*9880d681SAndroid Build Coastguard Worker // Shouldn't be anything else.
9241*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
9242*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9243*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "unexpected input in .req directive.");
9244*9880d681SAndroid Build Coastguard Worker return false;
9245*9880d681SAndroid Build Coastguard Worker }
9246*9880d681SAndroid Build Coastguard Worker
9247*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Consume the EndOfStatement
9248*9880d681SAndroid Build Coastguard Worker
9249*9880d681SAndroid Build Coastguard Worker if (RegisterReqs.insert(std::make_pair(Name, Reg)).first->second != Reg) {
9250*9880d681SAndroid Build Coastguard Worker Error(SRegLoc, "redefinition of '" + Name + "' does not match original.");
9251*9880d681SAndroid Build Coastguard Worker return false;
9252*9880d681SAndroid Build Coastguard Worker }
9253*9880d681SAndroid Build Coastguard Worker
9254*9880d681SAndroid Build Coastguard Worker return false;
9255*9880d681SAndroid Build Coastguard Worker }
9256*9880d681SAndroid Build Coastguard Worker
9257*9880d681SAndroid Build Coastguard Worker /// parseDirectiveUneq
9258*9880d681SAndroid Build Coastguard Worker /// ::= .unreq registername
parseDirectiveUnreq(SMLoc L)9259*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
9260*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9261*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Identifier)) {
9262*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9263*9880d681SAndroid Build Coastguard Worker Error(L, "unexpected input in .unreq directive.");
9264*9880d681SAndroid Build Coastguard Worker return false;
9265*9880d681SAndroid Build Coastguard Worker }
9266*9880d681SAndroid Build Coastguard Worker RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
9267*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // Eat the identifier.
9268*9880d681SAndroid Build Coastguard Worker return false;
9269*9880d681SAndroid Build Coastguard Worker }
9270*9880d681SAndroid Build Coastguard Worker
9271*9880d681SAndroid Build Coastguard Worker // After changing arch/CPU, try to put the ARM/Thumb mode back to what it was
9272*9880d681SAndroid Build Coastguard Worker // before, if supported by the new target, or emit mapping symbols for the mode
9273*9880d681SAndroid Build Coastguard Worker // switch.
FixModeAfterArchChange(bool WasThumb,SMLoc Loc)9274*9880d681SAndroid Build Coastguard Worker void ARMAsmParser::FixModeAfterArchChange(bool WasThumb, SMLoc Loc) {
9275*9880d681SAndroid Build Coastguard Worker if (WasThumb != isThumb()) {
9276*9880d681SAndroid Build Coastguard Worker if (WasThumb && hasThumb()) {
9277*9880d681SAndroid Build Coastguard Worker // Stay in Thumb mode
9278*9880d681SAndroid Build Coastguard Worker SwitchMode();
9279*9880d681SAndroid Build Coastguard Worker } else if (!WasThumb && hasARM()) {
9280*9880d681SAndroid Build Coastguard Worker // Stay in ARM mode
9281*9880d681SAndroid Build Coastguard Worker SwitchMode();
9282*9880d681SAndroid Build Coastguard Worker } else {
9283*9880d681SAndroid Build Coastguard Worker // Mode switch forced, because the new arch doesn't support the old mode.
9284*9880d681SAndroid Build Coastguard Worker getParser().getStreamer().EmitAssemblerFlag(isThumb() ? MCAF_Code16
9285*9880d681SAndroid Build Coastguard Worker : MCAF_Code32);
9286*9880d681SAndroid Build Coastguard Worker // Warn about the implcit mode switch. GAS does not switch modes here,
9287*9880d681SAndroid Build Coastguard Worker // but instead stays in the old mode, reporting an error on any following
9288*9880d681SAndroid Build Coastguard Worker // instructions as the mode does not exist on the target.
9289*9880d681SAndroid Build Coastguard Worker Warning(Loc, Twine("new target does not support ") +
9290*9880d681SAndroid Build Coastguard Worker (WasThumb ? "thumb" : "arm") + " mode, switching to " +
9291*9880d681SAndroid Build Coastguard Worker (!WasThumb ? "thumb" : "arm") + " mode");
9292*9880d681SAndroid Build Coastguard Worker }
9293*9880d681SAndroid Build Coastguard Worker }
9294*9880d681SAndroid Build Coastguard Worker }
9295*9880d681SAndroid Build Coastguard Worker
9296*9880d681SAndroid Build Coastguard Worker /// parseDirectiveArch
9297*9880d681SAndroid Build Coastguard Worker /// ::= .arch token
parseDirectiveArch(SMLoc L)9298*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
9299*9880d681SAndroid Build Coastguard Worker StringRef Arch = getParser().parseStringToEndOfStatement().trim();
9300*9880d681SAndroid Build Coastguard Worker
9301*9880d681SAndroid Build Coastguard Worker unsigned ID = ARM::parseArch(Arch);
9302*9880d681SAndroid Build Coastguard Worker
9303*9880d681SAndroid Build Coastguard Worker if (ID == ARM::AK_INVALID) {
9304*9880d681SAndroid Build Coastguard Worker Error(L, "Unknown arch name");
9305*9880d681SAndroid Build Coastguard Worker return false;
9306*9880d681SAndroid Build Coastguard Worker }
9307*9880d681SAndroid Build Coastguard Worker
9308*9880d681SAndroid Build Coastguard Worker bool WasThumb = isThumb();
9309*9880d681SAndroid Build Coastguard Worker Triple T;
9310*9880d681SAndroid Build Coastguard Worker MCSubtargetInfo &STI = copySTI();
9311*9880d681SAndroid Build Coastguard Worker STI.setDefaultFeatures("", ("+" + ARM::getArchName(ID)).str());
9312*9880d681SAndroid Build Coastguard Worker setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
9313*9880d681SAndroid Build Coastguard Worker FixModeAfterArchChange(WasThumb, L);
9314*9880d681SAndroid Build Coastguard Worker
9315*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitArch(ID);
9316*9880d681SAndroid Build Coastguard Worker return false;
9317*9880d681SAndroid Build Coastguard Worker }
9318*9880d681SAndroid Build Coastguard Worker
9319*9880d681SAndroid Build Coastguard Worker /// parseDirectiveEabiAttr
9320*9880d681SAndroid Build Coastguard Worker /// ::= .eabi_attribute int, int [, "str"]
9321*9880d681SAndroid Build Coastguard Worker /// ::= .eabi_attribute Tag_name, int [, "str"]
parseDirectiveEabiAttr(SMLoc L)9322*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
9323*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9324*9880d681SAndroid Build Coastguard Worker int64_t Tag;
9325*9880d681SAndroid Build Coastguard Worker SMLoc TagLoc;
9326*9880d681SAndroid Build Coastguard Worker TagLoc = Parser.getTok().getLoc();
9327*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Identifier)) {
9328*9880d681SAndroid Build Coastguard Worker StringRef Name = Parser.getTok().getIdentifier();
9329*9880d681SAndroid Build Coastguard Worker Tag = ARMBuildAttrs::AttrTypeFromString(Name);
9330*9880d681SAndroid Build Coastguard Worker if (Tag == -1) {
9331*9880d681SAndroid Build Coastguard Worker Error(TagLoc, "attribute name not recognised: " + Name);
9332*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9333*9880d681SAndroid Build Coastguard Worker return false;
9334*9880d681SAndroid Build Coastguard Worker }
9335*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9336*9880d681SAndroid Build Coastguard Worker } else {
9337*9880d681SAndroid Build Coastguard Worker const MCExpr *AttrExpr;
9338*9880d681SAndroid Build Coastguard Worker
9339*9880d681SAndroid Build Coastguard Worker TagLoc = Parser.getTok().getLoc();
9340*9880d681SAndroid Build Coastguard Worker if (Parser.parseExpression(AttrExpr)) {
9341*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9342*9880d681SAndroid Build Coastguard Worker return false;
9343*9880d681SAndroid Build Coastguard Worker }
9344*9880d681SAndroid Build Coastguard Worker
9345*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
9346*9880d681SAndroid Build Coastguard Worker if (!CE) {
9347*9880d681SAndroid Build Coastguard Worker Error(TagLoc, "expected numeric constant");
9348*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9349*9880d681SAndroid Build Coastguard Worker return false;
9350*9880d681SAndroid Build Coastguard Worker }
9351*9880d681SAndroid Build Coastguard Worker
9352*9880d681SAndroid Build Coastguard Worker Tag = CE->getValue();
9353*9880d681SAndroid Build Coastguard Worker }
9354*9880d681SAndroid Build Coastguard Worker
9355*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Comma)) {
9356*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "comma expected");
9357*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9358*9880d681SAndroid Build Coastguard Worker return false;
9359*9880d681SAndroid Build Coastguard Worker }
9360*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // skip comma
9361*9880d681SAndroid Build Coastguard Worker
9362*9880d681SAndroid Build Coastguard Worker StringRef StringValue = "";
9363*9880d681SAndroid Build Coastguard Worker bool IsStringValue = false;
9364*9880d681SAndroid Build Coastguard Worker
9365*9880d681SAndroid Build Coastguard Worker int64_t IntegerValue = 0;
9366*9880d681SAndroid Build Coastguard Worker bool IsIntegerValue = false;
9367*9880d681SAndroid Build Coastguard Worker
9368*9880d681SAndroid Build Coastguard Worker if (Tag == ARMBuildAttrs::CPU_raw_name || Tag == ARMBuildAttrs::CPU_name)
9369*9880d681SAndroid Build Coastguard Worker IsStringValue = true;
9370*9880d681SAndroid Build Coastguard Worker else if (Tag == ARMBuildAttrs::compatibility) {
9371*9880d681SAndroid Build Coastguard Worker IsStringValue = true;
9372*9880d681SAndroid Build Coastguard Worker IsIntegerValue = true;
9373*9880d681SAndroid Build Coastguard Worker } else if (Tag < 32 || Tag % 2 == 0)
9374*9880d681SAndroid Build Coastguard Worker IsIntegerValue = true;
9375*9880d681SAndroid Build Coastguard Worker else if (Tag % 2 == 1)
9376*9880d681SAndroid Build Coastguard Worker IsStringValue = true;
9377*9880d681SAndroid Build Coastguard Worker else
9378*9880d681SAndroid Build Coastguard Worker llvm_unreachable("invalid tag type");
9379*9880d681SAndroid Build Coastguard Worker
9380*9880d681SAndroid Build Coastguard Worker if (IsIntegerValue) {
9381*9880d681SAndroid Build Coastguard Worker const MCExpr *ValueExpr;
9382*9880d681SAndroid Build Coastguard Worker SMLoc ValueExprLoc = Parser.getTok().getLoc();
9383*9880d681SAndroid Build Coastguard Worker if (Parser.parseExpression(ValueExpr)) {
9384*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9385*9880d681SAndroid Build Coastguard Worker return false;
9386*9880d681SAndroid Build Coastguard Worker }
9387*9880d681SAndroid Build Coastguard Worker
9388*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
9389*9880d681SAndroid Build Coastguard Worker if (!CE) {
9390*9880d681SAndroid Build Coastguard Worker Error(ValueExprLoc, "expected numeric constant");
9391*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9392*9880d681SAndroid Build Coastguard Worker return false;
9393*9880d681SAndroid Build Coastguard Worker }
9394*9880d681SAndroid Build Coastguard Worker
9395*9880d681SAndroid Build Coastguard Worker IntegerValue = CE->getValue();
9396*9880d681SAndroid Build Coastguard Worker }
9397*9880d681SAndroid Build Coastguard Worker
9398*9880d681SAndroid Build Coastguard Worker if (Tag == ARMBuildAttrs::compatibility) {
9399*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Comma))
9400*9880d681SAndroid Build Coastguard Worker IsStringValue = false;
9401*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Comma)) {
9402*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "comma expected");
9403*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9404*9880d681SAndroid Build Coastguard Worker return false;
9405*9880d681SAndroid Build Coastguard Worker } else {
9406*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9407*9880d681SAndroid Build Coastguard Worker }
9408*9880d681SAndroid Build Coastguard Worker }
9409*9880d681SAndroid Build Coastguard Worker
9410*9880d681SAndroid Build Coastguard Worker if (IsStringValue) {
9411*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::String)) {
9412*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "bad string constant");
9413*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9414*9880d681SAndroid Build Coastguard Worker return false;
9415*9880d681SAndroid Build Coastguard Worker }
9416*9880d681SAndroid Build Coastguard Worker
9417*9880d681SAndroid Build Coastguard Worker StringValue = Parser.getTok().getStringContents();
9418*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9419*9880d681SAndroid Build Coastguard Worker }
9420*9880d681SAndroid Build Coastguard Worker
9421*9880d681SAndroid Build Coastguard Worker if (IsIntegerValue && IsStringValue) {
9422*9880d681SAndroid Build Coastguard Worker assert(Tag == ARMBuildAttrs::compatibility);
9423*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitIntTextAttribute(Tag, IntegerValue, StringValue);
9424*9880d681SAndroid Build Coastguard Worker } else if (IsIntegerValue)
9425*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitAttribute(Tag, IntegerValue);
9426*9880d681SAndroid Build Coastguard Worker else if (IsStringValue)
9427*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitTextAttribute(Tag, StringValue);
9428*9880d681SAndroid Build Coastguard Worker return false;
9429*9880d681SAndroid Build Coastguard Worker }
9430*9880d681SAndroid Build Coastguard Worker
9431*9880d681SAndroid Build Coastguard Worker /// parseDirectiveCPU
9432*9880d681SAndroid Build Coastguard Worker /// ::= .cpu str
parseDirectiveCPU(SMLoc L)9433*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveCPU(SMLoc L) {
9434*9880d681SAndroid Build Coastguard Worker StringRef CPU = getParser().parseStringToEndOfStatement().trim();
9435*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitTextAttribute(ARMBuildAttrs::CPU_name, CPU);
9436*9880d681SAndroid Build Coastguard Worker
9437*9880d681SAndroid Build Coastguard Worker // FIXME: This is using table-gen data, but should be moved to
9438*9880d681SAndroid Build Coastguard Worker // ARMTargetParser once that is table-gen'd.
9439*9880d681SAndroid Build Coastguard Worker if (!getSTI().isCPUStringValid(CPU)) {
9440*9880d681SAndroid Build Coastguard Worker Error(L, "Unknown CPU name");
9441*9880d681SAndroid Build Coastguard Worker return false;
9442*9880d681SAndroid Build Coastguard Worker }
9443*9880d681SAndroid Build Coastguard Worker
9444*9880d681SAndroid Build Coastguard Worker bool WasThumb = isThumb();
9445*9880d681SAndroid Build Coastguard Worker MCSubtargetInfo &STI = copySTI();
9446*9880d681SAndroid Build Coastguard Worker STI.setDefaultFeatures(CPU, "");
9447*9880d681SAndroid Build Coastguard Worker setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
9448*9880d681SAndroid Build Coastguard Worker FixModeAfterArchChange(WasThumb, L);
9449*9880d681SAndroid Build Coastguard Worker
9450*9880d681SAndroid Build Coastguard Worker return false;
9451*9880d681SAndroid Build Coastguard Worker }
9452*9880d681SAndroid Build Coastguard Worker /// parseDirectiveFPU
9453*9880d681SAndroid Build Coastguard Worker /// ::= .fpu str
parseDirectiveFPU(SMLoc L)9454*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveFPU(SMLoc L) {
9455*9880d681SAndroid Build Coastguard Worker SMLoc FPUNameLoc = getTok().getLoc();
9456*9880d681SAndroid Build Coastguard Worker StringRef FPU = getParser().parseStringToEndOfStatement().trim();
9457*9880d681SAndroid Build Coastguard Worker
9458*9880d681SAndroid Build Coastguard Worker unsigned ID = ARM::parseFPU(FPU);
9459*9880d681SAndroid Build Coastguard Worker std::vector<const char *> Features;
9460*9880d681SAndroid Build Coastguard Worker if (!ARM::getFPUFeatures(ID, Features)) {
9461*9880d681SAndroid Build Coastguard Worker Error(FPUNameLoc, "Unknown FPU name");
9462*9880d681SAndroid Build Coastguard Worker return false;
9463*9880d681SAndroid Build Coastguard Worker }
9464*9880d681SAndroid Build Coastguard Worker
9465*9880d681SAndroid Build Coastguard Worker MCSubtargetInfo &STI = copySTI();
9466*9880d681SAndroid Build Coastguard Worker for (auto Feature : Features)
9467*9880d681SAndroid Build Coastguard Worker STI.ApplyFeatureFlag(Feature);
9468*9880d681SAndroid Build Coastguard Worker setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
9469*9880d681SAndroid Build Coastguard Worker
9470*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitFPU(ID);
9471*9880d681SAndroid Build Coastguard Worker return false;
9472*9880d681SAndroid Build Coastguard Worker }
9473*9880d681SAndroid Build Coastguard Worker
9474*9880d681SAndroid Build Coastguard Worker /// parseDirectiveFnStart
9475*9880d681SAndroid Build Coastguard Worker /// ::= .fnstart
parseDirectiveFnStart(SMLoc L)9476*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) {
9477*9880d681SAndroid Build Coastguard Worker if (UC.hasFnStart()) {
9478*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart starts before the end of previous one");
9479*9880d681SAndroid Build Coastguard Worker UC.emitFnStartLocNotes();
9480*9880d681SAndroid Build Coastguard Worker return false;
9481*9880d681SAndroid Build Coastguard Worker }
9482*9880d681SAndroid Build Coastguard Worker
9483*9880d681SAndroid Build Coastguard Worker // Reset the unwind directives parser state
9484*9880d681SAndroid Build Coastguard Worker UC.reset();
9485*9880d681SAndroid Build Coastguard Worker
9486*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitFnStart();
9487*9880d681SAndroid Build Coastguard Worker
9488*9880d681SAndroid Build Coastguard Worker UC.recordFnStart(L);
9489*9880d681SAndroid Build Coastguard Worker return false;
9490*9880d681SAndroid Build Coastguard Worker }
9491*9880d681SAndroid Build Coastguard Worker
9492*9880d681SAndroid Build Coastguard Worker /// parseDirectiveFnEnd
9493*9880d681SAndroid Build Coastguard Worker /// ::= .fnend
parseDirectiveFnEnd(SMLoc L)9494*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) {
9495*9880d681SAndroid Build Coastguard Worker // Check the ordering of unwind directives
9496*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
9497*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .fnend directive");
9498*9880d681SAndroid Build Coastguard Worker return false;
9499*9880d681SAndroid Build Coastguard Worker }
9500*9880d681SAndroid Build Coastguard Worker
9501*9880d681SAndroid Build Coastguard Worker // Reset the unwind directives parser state
9502*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitFnEnd();
9503*9880d681SAndroid Build Coastguard Worker
9504*9880d681SAndroid Build Coastguard Worker UC.reset();
9505*9880d681SAndroid Build Coastguard Worker return false;
9506*9880d681SAndroid Build Coastguard Worker }
9507*9880d681SAndroid Build Coastguard Worker
9508*9880d681SAndroid Build Coastguard Worker /// parseDirectiveCantUnwind
9509*9880d681SAndroid Build Coastguard Worker /// ::= .cantunwind
parseDirectiveCantUnwind(SMLoc L)9510*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) {
9511*9880d681SAndroid Build Coastguard Worker UC.recordCantUnwind(L);
9512*9880d681SAndroid Build Coastguard Worker
9513*9880d681SAndroid Build Coastguard Worker // Check the ordering of unwind directives
9514*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
9515*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .cantunwind directive");
9516*9880d681SAndroid Build Coastguard Worker return false;
9517*9880d681SAndroid Build Coastguard Worker }
9518*9880d681SAndroid Build Coastguard Worker if (UC.hasHandlerData()) {
9519*9880d681SAndroid Build Coastguard Worker Error(L, ".cantunwind can't be used with .handlerdata directive");
9520*9880d681SAndroid Build Coastguard Worker UC.emitHandlerDataLocNotes();
9521*9880d681SAndroid Build Coastguard Worker return false;
9522*9880d681SAndroid Build Coastguard Worker }
9523*9880d681SAndroid Build Coastguard Worker if (UC.hasPersonality()) {
9524*9880d681SAndroid Build Coastguard Worker Error(L, ".cantunwind can't be used with .personality directive");
9525*9880d681SAndroid Build Coastguard Worker UC.emitPersonalityLocNotes();
9526*9880d681SAndroid Build Coastguard Worker return false;
9527*9880d681SAndroid Build Coastguard Worker }
9528*9880d681SAndroid Build Coastguard Worker
9529*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitCantUnwind();
9530*9880d681SAndroid Build Coastguard Worker return false;
9531*9880d681SAndroid Build Coastguard Worker }
9532*9880d681SAndroid Build Coastguard Worker
9533*9880d681SAndroid Build Coastguard Worker /// parseDirectivePersonality
9534*9880d681SAndroid Build Coastguard Worker /// ::= .personality name
parseDirectivePersonality(SMLoc L)9535*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectivePersonality(SMLoc L) {
9536*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9537*9880d681SAndroid Build Coastguard Worker bool HasExistingPersonality = UC.hasPersonality();
9538*9880d681SAndroid Build Coastguard Worker
9539*9880d681SAndroid Build Coastguard Worker UC.recordPersonality(L);
9540*9880d681SAndroid Build Coastguard Worker
9541*9880d681SAndroid Build Coastguard Worker // Check the ordering of unwind directives
9542*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
9543*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .personality directive");
9544*9880d681SAndroid Build Coastguard Worker return false;
9545*9880d681SAndroid Build Coastguard Worker }
9546*9880d681SAndroid Build Coastguard Worker if (UC.cantUnwind()) {
9547*9880d681SAndroid Build Coastguard Worker Error(L, ".personality can't be used with .cantunwind directive");
9548*9880d681SAndroid Build Coastguard Worker UC.emitCantUnwindLocNotes();
9549*9880d681SAndroid Build Coastguard Worker return false;
9550*9880d681SAndroid Build Coastguard Worker }
9551*9880d681SAndroid Build Coastguard Worker if (UC.hasHandlerData()) {
9552*9880d681SAndroid Build Coastguard Worker Error(L, ".personality must precede .handlerdata directive");
9553*9880d681SAndroid Build Coastguard Worker UC.emitHandlerDataLocNotes();
9554*9880d681SAndroid Build Coastguard Worker return false;
9555*9880d681SAndroid Build Coastguard Worker }
9556*9880d681SAndroid Build Coastguard Worker if (HasExistingPersonality) {
9557*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9558*9880d681SAndroid Build Coastguard Worker Error(L, "multiple personality directives");
9559*9880d681SAndroid Build Coastguard Worker UC.emitPersonalityLocNotes();
9560*9880d681SAndroid Build Coastguard Worker return false;
9561*9880d681SAndroid Build Coastguard Worker }
9562*9880d681SAndroid Build Coastguard Worker
9563*9880d681SAndroid Build Coastguard Worker // Parse the name of the personality routine
9564*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Identifier)) {
9565*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9566*9880d681SAndroid Build Coastguard Worker Error(L, "unexpected input in .personality directive.");
9567*9880d681SAndroid Build Coastguard Worker return false;
9568*9880d681SAndroid Build Coastguard Worker }
9569*9880d681SAndroid Build Coastguard Worker StringRef Name(Parser.getTok().getIdentifier());
9570*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9571*9880d681SAndroid Build Coastguard Worker
9572*9880d681SAndroid Build Coastguard Worker MCSymbol *PR = getParser().getContext().getOrCreateSymbol(Name);
9573*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitPersonality(PR);
9574*9880d681SAndroid Build Coastguard Worker return false;
9575*9880d681SAndroid Build Coastguard Worker }
9576*9880d681SAndroid Build Coastguard Worker
9577*9880d681SAndroid Build Coastguard Worker /// parseDirectiveHandlerData
9578*9880d681SAndroid Build Coastguard Worker /// ::= .handlerdata
parseDirectiveHandlerData(SMLoc L)9579*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) {
9580*9880d681SAndroid Build Coastguard Worker UC.recordHandlerData(L);
9581*9880d681SAndroid Build Coastguard Worker
9582*9880d681SAndroid Build Coastguard Worker // Check the ordering of unwind directives
9583*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
9584*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .personality directive");
9585*9880d681SAndroid Build Coastguard Worker return false;
9586*9880d681SAndroid Build Coastguard Worker }
9587*9880d681SAndroid Build Coastguard Worker if (UC.cantUnwind()) {
9588*9880d681SAndroid Build Coastguard Worker Error(L, ".handlerdata can't be used with .cantunwind directive");
9589*9880d681SAndroid Build Coastguard Worker UC.emitCantUnwindLocNotes();
9590*9880d681SAndroid Build Coastguard Worker return false;
9591*9880d681SAndroid Build Coastguard Worker }
9592*9880d681SAndroid Build Coastguard Worker
9593*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitHandlerData();
9594*9880d681SAndroid Build Coastguard Worker return false;
9595*9880d681SAndroid Build Coastguard Worker }
9596*9880d681SAndroid Build Coastguard Worker
9597*9880d681SAndroid Build Coastguard Worker /// parseDirectiveSetFP
9598*9880d681SAndroid Build Coastguard Worker /// ::= .setfp fpreg, spreg [, offset]
parseDirectiveSetFP(SMLoc L)9599*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) {
9600*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9601*9880d681SAndroid Build Coastguard Worker // Check the ordering of unwind directives
9602*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
9603*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .setfp directive");
9604*9880d681SAndroid Build Coastguard Worker return false;
9605*9880d681SAndroid Build Coastguard Worker }
9606*9880d681SAndroid Build Coastguard Worker if (UC.hasHandlerData()) {
9607*9880d681SAndroid Build Coastguard Worker Error(L, ".setfp must precede .handlerdata directive");
9608*9880d681SAndroid Build Coastguard Worker return false;
9609*9880d681SAndroid Build Coastguard Worker }
9610*9880d681SAndroid Build Coastguard Worker
9611*9880d681SAndroid Build Coastguard Worker // Parse fpreg
9612*9880d681SAndroid Build Coastguard Worker SMLoc FPRegLoc = Parser.getTok().getLoc();
9613*9880d681SAndroid Build Coastguard Worker int FPReg = tryParseRegister();
9614*9880d681SAndroid Build Coastguard Worker if (FPReg == -1) {
9615*9880d681SAndroid Build Coastguard Worker Error(FPRegLoc, "frame pointer register expected");
9616*9880d681SAndroid Build Coastguard Worker return false;
9617*9880d681SAndroid Build Coastguard Worker }
9618*9880d681SAndroid Build Coastguard Worker
9619*9880d681SAndroid Build Coastguard Worker // Consume comma
9620*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Comma)) {
9621*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "comma expected");
9622*9880d681SAndroid Build Coastguard Worker return false;
9623*9880d681SAndroid Build Coastguard Worker }
9624*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // skip comma
9625*9880d681SAndroid Build Coastguard Worker
9626*9880d681SAndroid Build Coastguard Worker // Parse spreg
9627*9880d681SAndroid Build Coastguard Worker SMLoc SPRegLoc = Parser.getTok().getLoc();
9628*9880d681SAndroid Build Coastguard Worker int SPReg = tryParseRegister();
9629*9880d681SAndroid Build Coastguard Worker if (SPReg == -1) {
9630*9880d681SAndroid Build Coastguard Worker Error(SPRegLoc, "stack pointer register expected");
9631*9880d681SAndroid Build Coastguard Worker return false;
9632*9880d681SAndroid Build Coastguard Worker }
9633*9880d681SAndroid Build Coastguard Worker
9634*9880d681SAndroid Build Coastguard Worker if (SPReg != ARM::SP && SPReg != UC.getFPReg()) {
9635*9880d681SAndroid Build Coastguard Worker Error(SPRegLoc, "register should be either $sp or the latest fp register");
9636*9880d681SAndroid Build Coastguard Worker return false;
9637*9880d681SAndroid Build Coastguard Worker }
9638*9880d681SAndroid Build Coastguard Worker
9639*9880d681SAndroid Build Coastguard Worker // Update the frame pointer register
9640*9880d681SAndroid Build Coastguard Worker UC.saveFPReg(FPReg);
9641*9880d681SAndroid Build Coastguard Worker
9642*9880d681SAndroid Build Coastguard Worker // Parse offset
9643*9880d681SAndroid Build Coastguard Worker int64_t Offset = 0;
9644*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Comma)) {
9645*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // skip comma
9646*9880d681SAndroid Build Coastguard Worker
9647*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Hash) &&
9648*9880d681SAndroid Build Coastguard Worker Parser.getTok().isNot(AsmToken::Dollar)) {
9649*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "'#' expected");
9650*9880d681SAndroid Build Coastguard Worker return false;
9651*9880d681SAndroid Build Coastguard Worker }
9652*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // skip hash token.
9653*9880d681SAndroid Build Coastguard Worker
9654*9880d681SAndroid Build Coastguard Worker const MCExpr *OffsetExpr;
9655*9880d681SAndroid Build Coastguard Worker SMLoc ExLoc = Parser.getTok().getLoc();
9656*9880d681SAndroid Build Coastguard Worker SMLoc EndLoc;
9657*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(OffsetExpr, EndLoc)) {
9658*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "malformed setfp offset");
9659*9880d681SAndroid Build Coastguard Worker return false;
9660*9880d681SAndroid Build Coastguard Worker }
9661*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
9662*9880d681SAndroid Build Coastguard Worker if (!CE) {
9663*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "setfp offset must be an immediate");
9664*9880d681SAndroid Build Coastguard Worker return false;
9665*9880d681SAndroid Build Coastguard Worker }
9666*9880d681SAndroid Build Coastguard Worker
9667*9880d681SAndroid Build Coastguard Worker Offset = CE->getValue();
9668*9880d681SAndroid Build Coastguard Worker }
9669*9880d681SAndroid Build Coastguard Worker
9670*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitSetFP(static_cast<unsigned>(FPReg),
9671*9880d681SAndroid Build Coastguard Worker static_cast<unsigned>(SPReg), Offset);
9672*9880d681SAndroid Build Coastguard Worker return false;
9673*9880d681SAndroid Build Coastguard Worker }
9674*9880d681SAndroid Build Coastguard Worker
9675*9880d681SAndroid Build Coastguard Worker /// parseDirective
9676*9880d681SAndroid Build Coastguard Worker /// ::= .pad offset
parseDirectivePad(SMLoc L)9677*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectivePad(SMLoc L) {
9678*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9679*9880d681SAndroid Build Coastguard Worker // Check the ordering of unwind directives
9680*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
9681*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .pad directive");
9682*9880d681SAndroid Build Coastguard Worker return false;
9683*9880d681SAndroid Build Coastguard Worker }
9684*9880d681SAndroid Build Coastguard Worker if (UC.hasHandlerData()) {
9685*9880d681SAndroid Build Coastguard Worker Error(L, ".pad must precede .handlerdata directive");
9686*9880d681SAndroid Build Coastguard Worker return false;
9687*9880d681SAndroid Build Coastguard Worker }
9688*9880d681SAndroid Build Coastguard Worker
9689*9880d681SAndroid Build Coastguard Worker // Parse the offset
9690*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Hash) &&
9691*9880d681SAndroid Build Coastguard Worker Parser.getTok().isNot(AsmToken::Dollar)) {
9692*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "'#' expected");
9693*9880d681SAndroid Build Coastguard Worker return false;
9694*9880d681SAndroid Build Coastguard Worker }
9695*9880d681SAndroid Build Coastguard Worker Parser.Lex(); // skip hash token.
9696*9880d681SAndroid Build Coastguard Worker
9697*9880d681SAndroid Build Coastguard Worker const MCExpr *OffsetExpr;
9698*9880d681SAndroid Build Coastguard Worker SMLoc ExLoc = Parser.getTok().getLoc();
9699*9880d681SAndroid Build Coastguard Worker SMLoc EndLoc;
9700*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(OffsetExpr, EndLoc)) {
9701*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "malformed pad offset");
9702*9880d681SAndroid Build Coastguard Worker return false;
9703*9880d681SAndroid Build Coastguard Worker }
9704*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
9705*9880d681SAndroid Build Coastguard Worker if (!CE) {
9706*9880d681SAndroid Build Coastguard Worker Error(ExLoc, "pad offset must be an immediate");
9707*9880d681SAndroid Build Coastguard Worker return false;
9708*9880d681SAndroid Build Coastguard Worker }
9709*9880d681SAndroid Build Coastguard Worker
9710*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitPad(CE->getValue());
9711*9880d681SAndroid Build Coastguard Worker return false;
9712*9880d681SAndroid Build Coastguard Worker }
9713*9880d681SAndroid Build Coastguard Worker
9714*9880d681SAndroid Build Coastguard Worker /// parseDirectiveRegSave
9715*9880d681SAndroid Build Coastguard Worker /// ::= .save { registers }
9716*9880d681SAndroid Build Coastguard Worker /// ::= .vsave { registers }
parseDirectiveRegSave(SMLoc L,bool IsVector)9717*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) {
9718*9880d681SAndroid Build Coastguard Worker // Check the ordering of unwind directives
9719*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
9720*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .save or .vsave directives");
9721*9880d681SAndroid Build Coastguard Worker return false;
9722*9880d681SAndroid Build Coastguard Worker }
9723*9880d681SAndroid Build Coastguard Worker if (UC.hasHandlerData()) {
9724*9880d681SAndroid Build Coastguard Worker Error(L, ".save or .vsave must precede .handlerdata directive");
9725*9880d681SAndroid Build Coastguard Worker return false;
9726*9880d681SAndroid Build Coastguard Worker }
9727*9880d681SAndroid Build Coastguard Worker
9728*9880d681SAndroid Build Coastguard Worker // RAII object to make sure parsed operands are deleted.
9729*9880d681SAndroid Build Coastguard Worker SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
9730*9880d681SAndroid Build Coastguard Worker
9731*9880d681SAndroid Build Coastguard Worker // Parse the register list
9732*9880d681SAndroid Build Coastguard Worker if (parseRegisterList(Operands))
9733*9880d681SAndroid Build Coastguard Worker return false;
9734*9880d681SAndroid Build Coastguard Worker ARMOperand &Op = (ARMOperand &)*Operands[0];
9735*9880d681SAndroid Build Coastguard Worker if (!IsVector && !Op.isRegList()) {
9736*9880d681SAndroid Build Coastguard Worker Error(L, ".save expects GPR registers");
9737*9880d681SAndroid Build Coastguard Worker return false;
9738*9880d681SAndroid Build Coastguard Worker }
9739*9880d681SAndroid Build Coastguard Worker if (IsVector && !Op.isDPRRegList()) {
9740*9880d681SAndroid Build Coastguard Worker Error(L, ".vsave expects DPR registers");
9741*9880d681SAndroid Build Coastguard Worker return false;
9742*9880d681SAndroid Build Coastguard Worker }
9743*9880d681SAndroid Build Coastguard Worker
9744*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitRegSave(Op.getRegList(), IsVector);
9745*9880d681SAndroid Build Coastguard Worker return false;
9746*9880d681SAndroid Build Coastguard Worker }
9747*9880d681SAndroid Build Coastguard Worker
9748*9880d681SAndroid Build Coastguard Worker /// parseDirectiveInst
9749*9880d681SAndroid Build Coastguard Worker /// ::= .inst opcode [, ...]
9750*9880d681SAndroid Build Coastguard Worker /// ::= .inst.n opcode [, ...]
9751*9880d681SAndroid Build Coastguard Worker /// ::= .inst.w opcode [, ...]
parseDirectiveInst(SMLoc Loc,char Suffix)9752*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) {
9753*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9754*9880d681SAndroid Build Coastguard Worker int Width;
9755*9880d681SAndroid Build Coastguard Worker
9756*9880d681SAndroid Build Coastguard Worker if (isThumb()) {
9757*9880d681SAndroid Build Coastguard Worker switch (Suffix) {
9758*9880d681SAndroid Build Coastguard Worker case 'n':
9759*9880d681SAndroid Build Coastguard Worker Width = 2;
9760*9880d681SAndroid Build Coastguard Worker break;
9761*9880d681SAndroid Build Coastguard Worker case 'w':
9762*9880d681SAndroid Build Coastguard Worker Width = 4;
9763*9880d681SAndroid Build Coastguard Worker break;
9764*9880d681SAndroid Build Coastguard Worker default:
9765*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9766*9880d681SAndroid Build Coastguard Worker Error(Loc, "cannot determine Thumb instruction size, "
9767*9880d681SAndroid Build Coastguard Worker "use inst.n/inst.w instead");
9768*9880d681SAndroid Build Coastguard Worker return false;
9769*9880d681SAndroid Build Coastguard Worker }
9770*9880d681SAndroid Build Coastguard Worker } else {
9771*9880d681SAndroid Build Coastguard Worker if (Suffix) {
9772*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9773*9880d681SAndroid Build Coastguard Worker Error(Loc, "width suffixes are invalid in ARM mode");
9774*9880d681SAndroid Build Coastguard Worker return false;
9775*9880d681SAndroid Build Coastguard Worker }
9776*9880d681SAndroid Build Coastguard Worker Width = 4;
9777*9880d681SAndroid Build Coastguard Worker }
9778*9880d681SAndroid Build Coastguard Worker
9779*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::EndOfStatement)) {
9780*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9781*9880d681SAndroid Build Coastguard Worker Error(Loc, "expected expression following directive");
9782*9880d681SAndroid Build Coastguard Worker return false;
9783*9880d681SAndroid Build Coastguard Worker }
9784*9880d681SAndroid Build Coastguard Worker
9785*9880d681SAndroid Build Coastguard Worker for (;;) {
9786*9880d681SAndroid Build Coastguard Worker const MCExpr *Expr;
9787*9880d681SAndroid Build Coastguard Worker
9788*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Expr)) {
9789*9880d681SAndroid Build Coastguard Worker Error(Loc, "expected expression");
9790*9880d681SAndroid Build Coastguard Worker return false;
9791*9880d681SAndroid Build Coastguard Worker }
9792*9880d681SAndroid Build Coastguard Worker
9793*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
9794*9880d681SAndroid Build Coastguard Worker if (!Value) {
9795*9880d681SAndroid Build Coastguard Worker Error(Loc, "expected constant expression");
9796*9880d681SAndroid Build Coastguard Worker return false;
9797*9880d681SAndroid Build Coastguard Worker }
9798*9880d681SAndroid Build Coastguard Worker
9799*9880d681SAndroid Build Coastguard Worker switch (Width) {
9800*9880d681SAndroid Build Coastguard Worker case 2:
9801*9880d681SAndroid Build Coastguard Worker if (Value->getValue() > 0xffff) {
9802*9880d681SAndroid Build Coastguard Worker Error(Loc, "inst.n operand is too big, use inst.w instead");
9803*9880d681SAndroid Build Coastguard Worker return false;
9804*9880d681SAndroid Build Coastguard Worker }
9805*9880d681SAndroid Build Coastguard Worker break;
9806*9880d681SAndroid Build Coastguard Worker case 4:
9807*9880d681SAndroid Build Coastguard Worker if (Value->getValue() > 0xffffffff) {
9808*9880d681SAndroid Build Coastguard Worker Error(Loc,
9809*9880d681SAndroid Build Coastguard Worker StringRef(Suffix ? "inst.w" : "inst") + " operand is too big");
9810*9880d681SAndroid Build Coastguard Worker return false;
9811*9880d681SAndroid Build Coastguard Worker }
9812*9880d681SAndroid Build Coastguard Worker break;
9813*9880d681SAndroid Build Coastguard Worker default:
9814*9880d681SAndroid Build Coastguard Worker llvm_unreachable("only supported widths are 2 and 4");
9815*9880d681SAndroid Build Coastguard Worker }
9816*9880d681SAndroid Build Coastguard Worker
9817*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitInst(Value->getValue(), Suffix);
9818*9880d681SAndroid Build Coastguard Worker
9819*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::EndOfStatement))
9820*9880d681SAndroid Build Coastguard Worker break;
9821*9880d681SAndroid Build Coastguard Worker
9822*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma)) {
9823*9880d681SAndroid Build Coastguard Worker Error(Loc, "unexpected token in directive");
9824*9880d681SAndroid Build Coastguard Worker return false;
9825*9880d681SAndroid Build Coastguard Worker }
9826*9880d681SAndroid Build Coastguard Worker
9827*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9828*9880d681SAndroid Build Coastguard Worker }
9829*9880d681SAndroid Build Coastguard Worker
9830*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9831*9880d681SAndroid Build Coastguard Worker return false;
9832*9880d681SAndroid Build Coastguard Worker }
9833*9880d681SAndroid Build Coastguard Worker
9834*9880d681SAndroid Build Coastguard Worker /// parseDirectiveLtorg
9835*9880d681SAndroid Build Coastguard Worker /// ::= .ltorg | .pool
parseDirectiveLtorg(SMLoc L)9836*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveLtorg(SMLoc L) {
9837*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitCurrentConstantPool();
9838*9880d681SAndroid Build Coastguard Worker return false;
9839*9880d681SAndroid Build Coastguard Worker }
9840*9880d681SAndroid Build Coastguard Worker
parseDirectiveEven(SMLoc L)9841*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveEven(SMLoc L) {
9842*9880d681SAndroid Build Coastguard Worker const MCSection *Section = getStreamer().getCurrentSection().first;
9843*9880d681SAndroid Build Coastguard Worker
9844*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
9845*9880d681SAndroid Build Coastguard Worker TokError("unexpected token in directive");
9846*9880d681SAndroid Build Coastguard Worker return false;
9847*9880d681SAndroid Build Coastguard Worker }
9848*9880d681SAndroid Build Coastguard Worker
9849*9880d681SAndroid Build Coastguard Worker if (!Section) {
9850*9880d681SAndroid Build Coastguard Worker getStreamer().InitSections(false);
9851*9880d681SAndroid Build Coastguard Worker Section = getStreamer().getCurrentSection().first;
9852*9880d681SAndroid Build Coastguard Worker }
9853*9880d681SAndroid Build Coastguard Worker
9854*9880d681SAndroid Build Coastguard Worker assert(Section && "must have section to emit alignment");
9855*9880d681SAndroid Build Coastguard Worker if (Section->UseCodeAlign())
9856*9880d681SAndroid Build Coastguard Worker getStreamer().EmitCodeAlignment(2);
9857*9880d681SAndroid Build Coastguard Worker else
9858*9880d681SAndroid Build Coastguard Worker getStreamer().EmitValueToAlignment(2);
9859*9880d681SAndroid Build Coastguard Worker
9860*9880d681SAndroid Build Coastguard Worker return false;
9861*9880d681SAndroid Build Coastguard Worker }
9862*9880d681SAndroid Build Coastguard Worker
9863*9880d681SAndroid Build Coastguard Worker /// parseDirectivePersonalityIndex
9864*9880d681SAndroid Build Coastguard Worker /// ::= .personalityindex index
parseDirectivePersonalityIndex(SMLoc L)9865*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) {
9866*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9867*9880d681SAndroid Build Coastguard Worker bool HasExistingPersonality = UC.hasPersonality();
9868*9880d681SAndroid Build Coastguard Worker
9869*9880d681SAndroid Build Coastguard Worker UC.recordPersonalityIndex(L);
9870*9880d681SAndroid Build Coastguard Worker
9871*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
9872*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9873*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .personalityindex directive");
9874*9880d681SAndroid Build Coastguard Worker return false;
9875*9880d681SAndroid Build Coastguard Worker }
9876*9880d681SAndroid Build Coastguard Worker if (UC.cantUnwind()) {
9877*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9878*9880d681SAndroid Build Coastguard Worker Error(L, ".personalityindex cannot be used with .cantunwind");
9879*9880d681SAndroid Build Coastguard Worker UC.emitCantUnwindLocNotes();
9880*9880d681SAndroid Build Coastguard Worker return false;
9881*9880d681SAndroid Build Coastguard Worker }
9882*9880d681SAndroid Build Coastguard Worker if (UC.hasHandlerData()) {
9883*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9884*9880d681SAndroid Build Coastguard Worker Error(L, ".personalityindex must precede .handlerdata directive");
9885*9880d681SAndroid Build Coastguard Worker UC.emitHandlerDataLocNotes();
9886*9880d681SAndroid Build Coastguard Worker return false;
9887*9880d681SAndroid Build Coastguard Worker }
9888*9880d681SAndroid Build Coastguard Worker if (HasExistingPersonality) {
9889*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9890*9880d681SAndroid Build Coastguard Worker Error(L, "multiple personality directives");
9891*9880d681SAndroid Build Coastguard Worker UC.emitPersonalityLocNotes();
9892*9880d681SAndroid Build Coastguard Worker return false;
9893*9880d681SAndroid Build Coastguard Worker }
9894*9880d681SAndroid Build Coastguard Worker
9895*9880d681SAndroid Build Coastguard Worker const MCExpr *IndexExpression;
9896*9880d681SAndroid Build Coastguard Worker SMLoc IndexLoc = Parser.getTok().getLoc();
9897*9880d681SAndroid Build Coastguard Worker if (Parser.parseExpression(IndexExpression)) {
9898*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9899*9880d681SAndroid Build Coastguard Worker return false;
9900*9880d681SAndroid Build Coastguard Worker }
9901*9880d681SAndroid Build Coastguard Worker
9902*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(IndexExpression);
9903*9880d681SAndroid Build Coastguard Worker if (!CE) {
9904*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9905*9880d681SAndroid Build Coastguard Worker Error(IndexLoc, "index must be a constant number");
9906*9880d681SAndroid Build Coastguard Worker return false;
9907*9880d681SAndroid Build Coastguard Worker }
9908*9880d681SAndroid Build Coastguard Worker if (CE->getValue() < 0 ||
9909*9880d681SAndroid Build Coastguard Worker CE->getValue() >= ARM::EHABI::NUM_PERSONALITY_INDEX) {
9910*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9911*9880d681SAndroid Build Coastguard Worker Error(IndexLoc, "personality routine index should be in range [0-3]");
9912*9880d681SAndroid Build Coastguard Worker return false;
9913*9880d681SAndroid Build Coastguard Worker }
9914*9880d681SAndroid Build Coastguard Worker
9915*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitPersonalityIndex(CE->getValue());
9916*9880d681SAndroid Build Coastguard Worker return false;
9917*9880d681SAndroid Build Coastguard Worker }
9918*9880d681SAndroid Build Coastguard Worker
9919*9880d681SAndroid Build Coastguard Worker /// parseDirectiveUnwindRaw
9920*9880d681SAndroid Build Coastguard Worker /// ::= .unwind_raw offset, opcode [, opcode...]
parseDirectiveUnwindRaw(SMLoc L)9921*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) {
9922*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
9923*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
9924*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9925*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .unwind_raw directives");
9926*9880d681SAndroid Build Coastguard Worker return false;
9927*9880d681SAndroid Build Coastguard Worker }
9928*9880d681SAndroid Build Coastguard Worker
9929*9880d681SAndroid Build Coastguard Worker int64_t StackOffset;
9930*9880d681SAndroid Build Coastguard Worker
9931*9880d681SAndroid Build Coastguard Worker const MCExpr *OffsetExpr;
9932*9880d681SAndroid Build Coastguard Worker SMLoc OffsetLoc = getLexer().getLoc();
9933*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::EndOfStatement) ||
9934*9880d681SAndroid Build Coastguard Worker getParser().parseExpression(OffsetExpr)) {
9935*9880d681SAndroid Build Coastguard Worker Error(OffsetLoc, "expected expression");
9936*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9937*9880d681SAndroid Build Coastguard Worker return false;
9938*9880d681SAndroid Build Coastguard Worker }
9939*9880d681SAndroid Build Coastguard Worker
9940*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
9941*9880d681SAndroid Build Coastguard Worker if (!CE) {
9942*9880d681SAndroid Build Coastguard Worker Error(OffsetLoc, "offset must be a constant");
9943*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9944*9880d681SAndroid Build Coastguard Worker return false;
9945*9880d681SAndroid Build Coastguard Worker }
9946*9880d681SAndroid Build Coastguard Worker
9947*9880d681SAndroid Build Coastguard Worker StackOffset = CE->getValue();
9948*9880d681SAndroid Build Coastguard Worker
9949*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma)) {
9950*9880d681SAndroid Build Coastguard Worker Error(getLexer().getLoc(), "expected comma");
9951*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9952*9880d681SAndroid Build Coastguard Worker return false;
9953*9880d681SAndroid Build Coastguard Worker }
9954*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9955*9880d681SAndroid Build Coastguard Worker
9956*9880d681SAndroid Build Coastguard Worker SmallVector<uint8_t, 16> Opcodes;
9957*9880d681SAndroid Build Coastguard Worker for (;;) {
9958*9880d681SAndroid Build Coastguard Worker const MCExpr *OE;
9959*9880d681SAndroid Build Coastguard Worker
9960*9880d681SAndroid Build Coastguard Worker SMLoc OpcodeLoc = getLexer().getLoc();
9961*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::EndOfStatement) || Parser.parseExpression(OE)) {
9962*9880d681SAndroid Build Coastguard Worker Error(OpcodeLoc, "expected opcode expression");
9963*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9964*9880d681SAndroid Build Coastguard Worker return false;
9965*9880d681SAndroid Build Coastguard Worker }
9966*9880d681SAndroid Build Coastguard Worker
9967*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *OC = dyn_cast<MCConstantExpr>(OE);
9968*9880d681SAndroid Build Coastguard Worker if (!OC) {
9969*9880d681SAndroid Build Coastguard Worker Error(OpcodeLoc, "opcode value must be a constant");
9970*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9971*9880d681SAndroid Build Coastguard Worker return false;
9972*9880d681SAndroid Build Coastguard Worker }
9973*9880d681SAndroid Build Coastguard Worker
9974*9880d681SAndroid Build Coastguard Worker const int64_t Opcode = OC->getValue();
9975*9880d681SAndroid Build Coastguard Worker if (Opcode & ~0xff) {
9976*9880d681SAndroid Build Coastguard Worker Error(OpcodeLoc, "invalid opcode");
9977*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9978*9880d681SAndroid Build Coastguard Worker return false;
9979*9880d681SAndroid Build Coastguard Worker }
9980*9880d681SAndroid Build Coastguard Worker
9981*9880d681SAndroid Build Coastguard Worker Opcodes.push_back(uint8_t(Opcode));
9982*9880d681SAndroid Build Coastguard Worker
9983*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::EndOfStatement))
9984*9880d681SAndroid Build Coastguard Worker break;
9985*9880d681SAndroid Build Coastguard Worker
9986*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma)) {
9987*9880d681SAndroid Build Coastguard Worker Error(getLexer().getLoc(), "unexpected token in directive");
9988*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
9989*9880d681SAndroid Build Coastguard Worker return false;
9990*9880d681SAndroid Build Coastguard Worker }
9991*9880d681SAndroid Build Coastguard Worker
9992*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9993*9880d681SAndroid Build Coastguard Worker }
9994*9880d681SAndroid Build Coastguard Worker
9995*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitUnwindRaw(StackOffset, Opcodes);
9996*9880d681SAndroid Build Coastguard Worker
9997*9880d681SAndroid Build Coastguard Worker Parser.Lex();
9998*9880d681SAndroid Build Coastguard Worker return false;
9999*9880d681SAndroid Build Coastguard Worker }
10000*9880d681SAndroid Build Coastguard Worker
10001*9880d681SAndroid Build Coastguard Worker /// parseDirectiveTLSDescSeq
10002*9880d681SAndroid Build Coastguard Worker /// ::= .tlsdescseq tls-variable
parseDirectiveTLSDescSeq(SMLoc L)10003*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) {
10004*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
10005*9880d681SAndroid Build Coastguard Worker
10006*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Identifier)) {
10007*9880d681SAndroid Build Coastguard Worker TokError("expected variable after '.tlsdescseq' directive");
10008*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10009*9880d681SAndroid Build Coastguard Worker return false;
10010*9880d681SAndroid Build Coastguard Worker }
10011*9880d681SAndroid Build Coastguard Worker
10012*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr *SRE =
10013*9880d681SAndroid Build Coastguard Worker MCSymbolRefExpr::create(Parser.getTok().getIdentifier(),
10014*9880d681SAndroid Build Coastguard Worker MCSymbolRefExpr::VK_ARM_TLSDESCSEQ, getContext());
10015*9880d681SAndroid Build Coastguard Worker Lex();
10016*9880d681SAndroid Build Coastguard Worker
10017*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
10018*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "unexpected token");
10019*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10020*9880d681SAndroid Build Coastguard Worker return false;
10021*9880d681SAndroid Build Coastguard Worker }
10022*9880d681SAndroid Build Coastguard Worker
10023*9880d681SAndroid Build Coastguard Worker getTargetStreamer().AnnotateTLSDescriptorSequence(SRE);
10024*9880d681SAndroid Build Coastguard Worker return false;
10025*9880d681SAndroid Build Coastguard Worker }
10026*9880d681SAndroid Build Coastguard Worker
10027*9880d681SAndroid Build Coastguard Worker /// parseDirectiveMovSP
10028*9880d681SAndroid Build Coastguard Worker /// ::= .movsp reg [, #offset]
parseDirectiveMovSP(SMLoc L)10029*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) {
10030*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
10031*9880d681SAndroid Build Coastguard Worker if (!UC.hasFnStart()) {
10032*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10033*9880d681SAndroid Build Coastguard Worker Error(L, ".fnstart must precede .movsp directives");
10034*9880d681SAndroid Build Coastguard Worker return false;
10035*9880d681SAndroid Build Coastguard Worker }
10036*9880d681SAndroid Build Coastguard Worker if (UC.getFPReg() != ARM::SP) {
10037*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10038*9880d681SAndroid Build Coastguard Worker Error(L, "unexpected .movsp directive");
10039*9880d681SAndroid Build Coastguard Worker return false;
10040*9880d681SAndroid Build Coastguard Worker }
10041*9880d681SAndroid Build Coastguard Worker
10042*9880d681SAndroid Build Coastguard Worker SMLoc SPRegLoc = Parser.getTok().getLoc();
10043*9880d681SAndroid Build Coastguard Worker int SPReg = tryParseRegister();
10044*9880d681SAndroid Build Coastguard Worker if (SPReg == -1) {
10045*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10046*9880d681SAndroid Build Coastguard Worker Error(SPRegLoc, "register expected");
10047*9880d681SAndroid Build Coastguard Worker return false;
10048*9880d681SAndroid Build Coastguard Worker }
10049*9880d681SAndroid Build Coastguard Worker
10050*9880d681SAndroid Build Coastguard Worker if (SPReg == ARM::SP || SPReg == ARM::PC) {
10051*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10052*9880d681SAndroid Build Coastguard Worker Error(SPRegLoc, "sp and pc are not permitted in .movsp directive");
10053*9880d681SAndroid Build Coastguard Worker return false;
10054*9880d681SAndroid Build Coastguard Worker }
10055*9880d681SAndroid Build Coastguard Worker
10056*9880d681SAndroid Build Coastguard Worker int64_t Offset = 0;
10057*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().is(AsmToken::Comma)) {
10058*9880d681SAndroid Build Coastguard Worker Parser.Lex();
10059*9880d681SAndroid Build Coastguard Worker
10060*9880d681SAndroid Build Coastguard Worker if (Parser.getTok().isNot(AsmToken::Hash)) {
10061*9880d681SAndroid Build Coastguard Worker Error(Parser.getTok().getLoc(), "expected #constant");
10062*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10063*9880d681SAndroid Build Coastguard Worker return false;
10064*9880d681SAndroid Build Coastguard Worker }
10065*9880d681SAndroid Build Coastguard Worker Parser.Lex();
10066*9880d681SAndroid Build Coastguard Worker
10067*9880d681SAndroid Build Coastguard Worker const MCExpr *OffsetExpr;
10068*9880d681SAndroid Build Coastguard Worker SMLoc OffsetLoc = Parser.getTok().getLoc();
10069*9880d681SAndroid Build Coastguard Worker if (Parser.parseExpression(OffsetExpr)) {
10070*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10071*9880d681SAndroid Build Coastguard Worker Error(OffsetLoc, "malformed offset expression");
10072*9880d681SAndroid Build Coastguard Worker return false;
10073*9880d681SAndroid Build Coastguard Worker }
10074*9880d681SAndroid Build Coastguard Worker
10075*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
10076*9880d681SAndroid Build Coastguard Worker if (!CE) {
10077*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10078*9880d681SAndroid Build Coastguard Worker Error(OffsetLoc, "offset must be an immediate constant");
10079*9880d681SAndroid Build Coastguard Worker return false;
10080*9880d681SAndroid Build Coastguard Worker }
10081*9880d681SAndroid Build Coastguard Worker
10082*9880d681SAndroid Build Coastguard Worker Offset = CE->getValue();
10083*9880d681SAndroid Build Coastguard Worker }
10084*9880d681SAndroid Build Coastguard Worker
10085*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitMovSP(SPReg, Offset);
10086*9880d681SAndroid Build Coastguard Worker UC.saveFPReg(SPReg);
10087*9880d681SAndroid Build Coastguard Worker
10088*9880d681SAndroid Build Coastguard Worker return false;
10089*9880d681SAndroid Build Coastguard Worker }
10090*9880d681SAndroid Build Coastguard Worker
10091*9880d681SAndroid Build Coastguard Worker /// parseDirectiveObjectArch
10092*9880d681SAndroid Build Coastguard Worker /// ::= .object_arch name
parseDirectiveObjectArch(SMLoc L)10093*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) {
10094*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
10095*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Identifier)) {
10096*9880d681SAndroid Build Coastguard Worker Error(getLexer().getLoc(), "unexpected token");
10097*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10098*9880d681SAndroid Build Coastguard Worker return false;
10099*9880d681SAndroid Build Coastguard Worker }
10100*9880d681SAndroid Build Coastguard Worker
10101*9880d681SAndroid Build Coastguard Worker StringRef Arch = Parser.getTok().getString();
10102*9880d681SAndroid Build Coastguard Worker SMLoc ArchLoc = Parser.getTok().getLoc();
10103*9880d681SAndroid Build Coastguard Worker Lex();
10104*9880d681SAndroid Build Coastguard Worker
10105*9880d681SAndroid Build Coastguard Worker unsigned ID = ARM::parseArch(Arch);
10106*9880d681SAndroid Build Coastguard Worker
10107*9880d681SAndroid Build Coastguard Worker if (ID == ARM::AK_INVALID) {
10108*9880d681SAndroid Build Coastguard Worker Error(ArchLoc, "unknown architecture '" + Arch + "'");
10109*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10110*9880d681SAndroid Build Coastguard Worker return false;
10111*9880d681SAndroid Build Coastguard Worker }
10112*9880d681SAndroid Build Coastguard Worker
10113*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitObjectArch(ID);
10114*9880d681SAndroid Build Coastguard Worker
10115*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
10116*9880d681SAndroid Build Coastguard Worker Error(getLexer().getLoc(), "unexpected token");
10117*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10118*9880d681SAndroid Build Coastguard Worker }
10119*9880d681SAndroid Build Coastguard Worker
10120*9880d681SAndroid Build Coastguard Worker return false;
10121*9880d681SAndroid Build Coastguard Worker }
10122*9880d681SAndroid Build Coastguard Worker
10123*9880d681SAndroid Build Coastguard Worker /// parseDirectiveAlign
10124*9880d681SAndroid Build Coastguard Worker /// ::= .align
parseDirectiveAlign(SMLoc L)10125*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveAlign(SMLoc L) {
10126*9880d681SAndroid Build Coastguard Worker // NOTE: if this is not the end of the statement, fall back to the target
10127*9880d681SAndroid Build Coastguard Worker // agnostic handling for this directive which will correctly handle this.
10128*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement))
10129*9880d681SAndroid Build Coastguard Worker return true;
10130*9880d681SAndroid Build Coastguard Worker
10131*9880d681SAndroid Build Coastguard Worker // '.align' is target specifically handled to mean 2**2 byte alignment.
10132*9880d681SAndroid Build Coastguard Worker const MCSection *Section = getStreamer().getCurrentSection().first;
10133*9880d681SAndroid Build Coastguard Worker assert(Section && "must have section to emit alignment");
10134*9880d681SAndroid Build Coastguard Worker if (Section->UseCodeAlign())
10135*9880d681SAndroid Build Coastguard Worker getStreamer().EmitCodeAlignment(4, 0);
10136*9880d681SAndroid Build Coastguard Worker else
10137*9880d681SAndroid Build Coastguard Worker getStreamer().EmitValueToAlignment(4, 0, 1, 0);
10138*9880d681SAndroid Build Coastguard Worker
10139*9880d681SAndroid Build Coastguard Worker return false;
10140*9880d681SAndroid Build Coastguard Worker }
10141*9880d681SAndroid Build Coastguard Worker
10142*9880d681SAndroid Build Coastguard Worker /// parseDirectiveThumbSet
10143*9880d681SAndroid Build Coastguard Worker /// ::= .thumb_set name, value
parseDirectiveThumbSet(SMLoc L)10144*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) {
10145*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
10146*9880d681SAndroid Build Coastguard Worker
10147*9880d681SAndroid Build Coastguard Worker StringRef Name;
10148*9880d681SAndroid Build Coastguard Worker if (Parser.parseIdentifier(Name)) {
10149*9880d681SAndroid Build Coastguard Worker TokError("expected identifier after '.thumb_set'");
10150*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10151*9880d681SAndroid Build Coastguard Worker return false;
10152*9880d681SAndroid Build Coastguard Worker }
10153*9880d681SAndroid Build Coastguard Worker
10154*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma)) {
10155*9880d681SAndroid Build Coastguard Worker TokError("expected comma after name '" + Name + "'");
10156*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10157*9880d681SAndroid Build Coastguard Worker return false;
10158*9880d681SAndroid Build Coastguard Worker }
10159*9880d681SAndroid Build Coastguard Worker Lex();
10160*9880d681SAndroid Build Coastguard Worker
10161*9880d681SAndroid Build Coastguard Worker MCSymbol *Sym;
10162*9880d681SAndroid Build Coastguard Worker const MCExpr *Value;
10163*9880d681SAndroid Build Coastguard Worker if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,
10164*9880d681SAndroid Build Coastguard Worker Parser, Sym, Value))
10165*9880d681SAndroid Build Coastguard Worker return true;
10166*9880d681SAndroid Build Coastguard Worker
10167*9880d681SAndroid Build Coastguard Worker getTargetStreamer().emitThumbSet(Sym, Value);
10168*9880d681SAndroid Build Coastguard Worker return false;
10169*9880d681SAndroid Build Coastguard Worker }
10170*9880d681SAndroid Build Coastguard Worker
10171*9880d681SAndroid Build Coastguard Worker /// Force static initialization.
LLVMInitializeARMAsmParser()10172*9880d681SAndroid Build Coastguard Worker extern "C" void LLVMInitializeARMAsmParser() {
10173*9880d681SAndroid Build Coastguard Worker RegisterMCAsmParser<ARMAsmParser> X(TheARMLETarget);
10174*9880d681SAndroid Build Coastguard Worker RegisterMCAsmParser<ARMAsmParser> Y(TheARMBETarget);
10175*9880d681SAndroid Build Coastguard Worker RegisterMCAsmParser<ARMAsmParser> A(TheThumbLETarget);
10176*9880d681SAndroid Build Coastguard Worker RegisterMCAsmParser<ARMAsmParser> B(TheThumbBETarget);
10177*9880d681SAndroid Build Coastguard Worker }
10178*9880d681SAndroid Build Coastguard Worker
10179*9880d681SAndroid Build Coastguard Worker #define GET_REGISTER_MATCHER
10180*9880d681SAndroid Build Coastguard Worker #define GET_SUBTARGET_FEATURE_NAME
10181*9880d681SAndroid Build Coastguard Worker #define GET_MATCHER_IMPLEMENTATION
10182*9880d681SAndroid Build Coastguard Worker #include "ARMGenAsmMatcher.inc"
10183*9880d681SAndroid Build Coastguard Worker
10184*9880d681SAndroid Build Coastguard Worker // FIXME: This structure should be moved inside ARMTargetParser
10185*9880d681SAndroid Build Coastguard Worker // when we start to table-generate them, and we can use the ARM
10186*9880d681SAndroid Build Coastguard Worker // flags below, that were generated by table-gen.
10187*9880d681SAndroid Build Coastguard Worker static const struct {
10188*9880d681SAndroid Build Coastguard Worker const unsigned Kind;
10189*9880d681SAndroid Build Coastguard Worker const uint64_t ArchCheck;
10190*9880d681SAndroid Build Coastguard Worker const FeatureBitset Features;
10191*9880d681SAndroid Build Coastguard Worker } Extensions[] = {
10192*9880d681SAndroid Build Coastguard Worker { ARM::AEK_CRC, Feature_HasV8, {ARM::FeatureCRC} },
10193*9880d681SAndroid Build Coastguard Worker { ARM::AEK_CRYPTO, Feature_HasV8,
10194*9880d681SAndroid Build Coastguard Worker {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} },
10195*9880d681SAndroid Build Coastguard Worker { ARM::AEK_FP, Feature_HasV8, {ARM::FeatureFPARMv8} },
10196*9880d681SAndroid Build Coastguard Worker { (ARM::AEK_HWDIV | ARM::AEK_HWDIVARM), Feature_HasV7 | Feature_IsNotMClass,
10197*9880d681SAndroid Build Coastguard Worker {ARM::FeatureHWDiv, ARM::FeatureHWDivARM} },
10198*9880d681SAndroid Build Coastguard Worker { ARM::AEK_MP, Feature_HasV7 | Feature_IsNotMClass, {ARM::FeatureMP} },
10199*9880d681SAndroid Build Coastguard Worker { ARM::AEK_SIMD, Feature_HasV8, {ARM::FeatureNEON, ARM::FeatureFPARMv8} },
10200*9880d681SAndroid Build Coastguard Worker { ARM::AEK_SEC, Feature_HasV6K, {ARM::FeatureTrustZone} },
10201*9880d681SAndroid Build Coastguard Worker // FIXME: Only available in A-class, isel not predicated
10202*9880d681SAndroid Build Coastguard Worker { ARM::AEK_VIRT, Feature_HasV7, {ARM::FeatureVirtualization} },
10203*9880d681SAndroid Build Coastguard Worker { ARM::AEK_FP16, Feature_HasV8_2a, {ARM::FeatureFPARMv8, ARM::FeatureFullFP16} },
10204*9880d681SAndroid Build Coastguard Worker { ARM::AEK_RAS, Feature_HasV8, {ARM::FeatureRAS} },
10205*9880d681SAndroid Build Coastguard Worker // FIXME: Unsupported extensions.
10206*9880d681SAndroid Build Coastguard Worker { ARM::AEK_OS, Feature_None, {} },
10207*9880d681SAndroid Build Coastguard Worker { ARM::AEK_IWMMXT, Feature_None, {} },
10208*9880d681SAndroid Build Coastguard Worker { ARM::AEK_IWMMXT2, Feature_None, {} },
10209*9880d681SAndroid Build Coastguard Worker { ARM::AEK_MAVERICK, Feature_None, {} },
10210*9880d681SAndroid Build Coastguard Worker { ARM::AEK_XSCALE, Feature_None, {} },
10211*9880d681SAndroid Build Coastguard Worker };
10212*9880d681SAndroid Build Coastguard Worker
10213*9880d681SAndroid Build Coastguard Worker /// parseDirectiveArchExtension
10214*9880d681SAndroid Build Coastguard Worker /// ::= .arch_extension [no]feature
parseDirectiveArchExtension(SMLoc L)10215*9880d681SAndroid Build Coastguard Worker bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
10216*9880d681SAndroid Build Coastguard Worker MCAsmParser &Parser = getParser();
10217*9880d681SAndroid Build Coastguard Worker
10218*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Identifier)) {
10219*9880d681SAndroid Build Coastguard Worker Error(getLexer().getLoc(), "unexpected token");
10220*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10221*9880d681SAndroid Build Coastguard Worker return false;
10222*9880d681SAndroid Build Coastguard Worker }
10223*9880d681SAndroid Build Coastguard Worker
10224*9880d681SAndroid Build Coastguard Worker StringRef Name = Parser.getTok().getString();
10225*9880d681SAndroid Build Coastguard Worker SMLoc ExtLoc = Parser.getTok().getLoc();
10226*9880d681SAndroid Build Coastguard Worker Lex();
10227*9880d681SAndroid Build Coastguard Worker
10228*9880d681SAndroid Build Coastguard Worker bool EnableFeature = true;
10229*9880d681SAndroid Build Coastguard Worker if (Name.startswith_lower("no")) {
10230*9880d681SAndroid Build Coastguard Worker EnableFeature = false;
10231*9880d681SAndroid Build Coastguard Worker Name = Name.substr(2);
10232*9880d681SAndroid Build Coastguard Worker }
10233*9880d681SAndroid Build Coastguard Worker unsigned FeatureKind = ARM::parseArchExt(Name);
10234*9880d681SAndroid Build Coastguard Worker if (FeatureKind == ARM::AEK_INVALID)
10235*9880d681SAndroid Build Coastguard Worker Error(ExtLoc, "unknown architectural extension: " + Name);
10236*9880d681SAndroid Build Coastguard Worker
10237*9880d681SAndroid Build Coastguard Worker for (const auto &Extension : Extensions) {
10238*9880d681SAndroid Build Coastguard Worker if (Extension.Kind != FeatureKind)
10239*9880d681SAndroid Build Coastguard Worker continue;
10240*9880d681SAndroid Build Coastguard Worker
10241*9880d681SAndroid Build Coastguard Worker if (Extension.Features.none())
10242*9880d681SAndroid Build Coastguard Worker report_fatal_error("unsupported architectural extension: " + Name);
10243*9880d681SAndroid Build Coastguard Worker
10244*9880d681SAndroid Build Coastguard Worker if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) {
10245*9880d681SAndroid Build Coastguard Worker Error(ExtLoc, "architectural extension '" + Name + "' is not "
10246*9880d681SAndroid Build Coastguard Worker "allowed for the current base architecture");
10247*9880d681SAndroid Build Coastguard Worker return false;
10248*9880d681SAndroid Build Coastguard Worker }
10249*9880d681SAndroid Build Coastguard Worker
10250*9880d681SAndroid Build Coastguard Worker MCSubtargetInfo &STI = copySTI();
10251*9880d681SAndroid Build Coastguard Worker FeatureBitset ToggleFeatures = EnableFeature
10252*9880d681SAndroid Build Coastguard Worker ? (~STI.getFeatureBits() & Extension.Features)
10253*9880d681SAndroid Build Coastguard Worker : ( STI.getFeatureBits() & Extension.Features);
10254*9880d681SAndroid Build Coastguard Worker
10255*9880d681SAndroid Build Coastguard Worker uint64_t Features =
10256*9880d681SAndroid Build Coastguard Worker ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
10257*9880d681SAndroid Build Coastguard Worker setAvailableFeatures(Features);
10258*9880d681SAndroid Build Coastguard Worker return false;
10259*9880d681SAndroid Build Coastguard Worker }
10260*9880d681SAndroid Build Coastguard Worker
10261*9880d681SAndroid Build Coastguard Worker Error(ExtLoc, "unknown architectural extension: " + Name);
10262*9880d681SAndroid Build Coastguard Worker Parser.eatToEndOfStatement();
10263*9880d681SAndroid Build Coastguard Worker return false;
10264*9880d681SAndroid Build Coastguard Worker }
10265*9880d681SAndroid Build Coastguard Worker
10266*9880d681SAndroid Build Coastguard Worker // Define this matcher function after the auto-generated include so we
10267*9880d681SAndroid Build Coastguard Worker // have the match class enum definitions.
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)10268*9880d681SAndroid Build Coastguard Worker unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
10269*9880d681SAndroid Build Coastguard Worker unsigned Kind) {
10270*9880d681SAndroid Build Coastguard Worker ARMOperand &Op = static_cast<ARMOperand &>(AsmOp);
10271*9880d681SAndroid Build Coastguard Worker // If the kind is a token for a literal immediate, check if our asm
10272*9880d681SAndroid Build Coastguard Worker // operand matches. This is for InstAliases which have a fixed-value
10273*9880d681SAndroid Build Coastguard Worker // immediate in the syntax.
10274*9880d681SAndroid Build Coastguard Worker switch (Kind) {
10275*9880d681SAndroid Build Coastguard Worker default: break;
10276*9880d681SAndroid Build Coastguard Worker case MCK__35_0:
10277*9880d681SAndroid Build Coastguard Worker if (Op.isImm())
10278*9880d681SAndroid Build Coastguard Worker if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm()))
10279*9880d681SAndroid Build Coastguard Worker if (CE->getValue() == 0)
10280*9880d681SAndroid Build Coastguard Worker return Match_Success;
10281*9880d681SAndroid Build Coastguard Worker break;
10282*9880d681SAndroid Build Coastguard Worker case MCK_ModImm:
10283*9880d681SAndroid Build Coastguard Worker if (Op.isImm()) {
10284*9880d681SAndroid Build Coastguard Worker const MCExpr *SOExpr = Op.getImm();
10285*9880d681SAndroid Build Coastguard Worker int64_t Value;
10286*9880d681SAndroid Build Coastguard Worker if (!SOExpr->evaluateAsAbsolute(Value))
10287*9880d681SAndroid Build Coastguard Worker return Match_Success;
10288*9880d681SAndroid Build Coastguard Worker assert((Value >= INT32_MIN && Value <= UINT32_MAX) &&
10289*9880d681SAndroid Build Coastguard Worker "expression value must be representable in 32 bits");
10290*9880d681SAndroid Build Coastguard Worker }
10291*9880d681SAndroid Build Coastguard Worker break;
10292*9880d681SAndroid Build Coastguard Worker case MCK_rGPR:
10293*9880d681SAndroid Build Coastguard Worker if (hasV8Ops() && Op.isReg() && Op.getReg() == ARM::SP)
10294*9880d681SAndroid Build Coastguard Worker return Match_Success;
10295*9880d681SAndroid Build Coastguard Worker break;
10296*9880d681SAndroid Build Coastguard Worker case MCK_GPRPair:
10297*9880d681SAndroid Build Coastguard Worker if (Op.isReg() &&
10298*9880d681SAndroid Build Coastguard Worker MRI->getRegClass(ARM::GPRRegClassID).contains(Op.getReg()))
10299*9880d681SAndroid Build Coastguard Worker return Match_Success;
10300*9880d681SAndroid Build Coastguard Worker break;
10301*9880d681SAndroid Build Coastguard Worker }
10302*9880d681SAndroid Build Coastguard Worker return Match_InvalidOperand;
10303*9880d681SAndroid Build Coastguard Worker }
10304