Bug Summary

File:lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Warning:line 271, column 36
The result of the left shift is undefined due to shifting by '32', which is greater or equal to the width of type 'int'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ARMAsmParser.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/lib/Target/ARM/AsmParser -I /build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser -I /build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/lib/Target/ARM -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn329677/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/lib/Target/ARM/AsmParser -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-04-11-031539-24776-1 -x c++ /build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
1//===- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ARMFeatures.h"
11#include "Utils/ARMBaseInfo.h"
12#include "MCTargetDesc/ARMAddressingModes.h"
13#include "MCTargetDesc/ARMBaseInfo.h"
14#include "MCTargetDesc/ARMMCExpr.h"
15#include "MCTargetDesc/ARMMCTargetDesc.h"
16#include "llvm/ADT/APFloat.h"
17#include "llvm/ADT/APInt.h"
18#include "llvm/ADT/None.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/SmallSet.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringMap.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/ADT/Triple.h"
26#include "llvm/ADT/Twine.h"
27#include "llvm/MC/MCContext.h"
28#include "llvm/MC/MCExpr.h"
29#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCInstrDesc.h"
31#include "llvm/MC/MCInstrInfo.h"
32#include "llvm/MC/MCObjectFileInfo.h"
33#include "llvm/MC/MCParser/MCAsmLexer.h"
34#include "llvm/MC/MCParser/MCAsmParser.h"
35#include "llvm/MC/MCParser/MCAsmParserExtension.h"
36#include "llvm/MC/MCParser/MCAsmParserUtils.h"
37#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
38#include "llvm/MC/MCParser/MCTargetAsmParser.h"
39#include "llvm/MC/MCRegisterInfo.h"
40#include "llvm/MC/MCSection.h"
41#include "llvm/MC/MCStreamer.h"
42#include "llvm/MC/MCSubtargetInfo.h"
43#include "llvm/MC/MCSymbol.h"
44#include "llvm/MC/SubtargetFeature.h"
45#include "llvm/Support/ARMBuildAttributes.h"
46#include "llvm/Support/ARMEHABI.h"
47#include "llvm/Support/Casting.h"
48#include "llvm/Support/CommandLine.h"
49#include "llvm/Support/Compiler.h"
50#include "llvm/Support/ErrorHandling.h"
51#include "llvm/Support/MathExtras.h"
52#include "llvm/Support/SMLoc.h"
53#include "llvm/Support/TargetParser.h"
54#include "llvm/Support/TargetRegistry.h"
55#include "llvm/Support/raw_ostream.h"
56#include <algorithm>
57#include <cassert>
58#include <cstddef>
59#include <cstdint>
60#include <iterator>
61#include <limits>
62#include <memory>
63#include <string>
64#include <utility>
65#include <vector>
66
67#define DEBUG_TYPE"asm-parser" "asm-parser"
68
69using namespace llvm;
70
71namespace {
72
73enum class ImplicitItModeTy { Always, Never, ARMOnly, ThumbOnly };
74
75static cl::opt<ImplicitItModeTy> ImplicitItMode(
76 "arm-implicit-it", cl::init(ImplicitItModeTy::ARMOnly),
77 cl::desc("Allow conditional instructions outdside of an IT block"),
78 cl::values(clEnumValN(ImplicitItModeTy::Always, "always",llvm::cl::OptionEnumValue { "always", int(ImplicitItModeTy::Always
), "Accept in both ISAs, emit implicit ITs in Thumb" }
79 "Accept in both ISAs, emit implicit ITs in Thumb")llvm::cl::OptionEnumValue { "always", int(ImplicitItModeTy::Always
), "Accept in both ISAs, emit implicit ITs in Thumb" }
,
80 clEnumValN(ImplicitItModeTy::Never, "never",llvm::cl::OptionEnumValue { "never", int(ImplicitItModeTy::Never
), "Warn in ARM, reject in Thumb" }
81 "Warn in ARM, reject in Thumb")llvm::cl::OptionEnumValue { "never", int(ImplicitItModeTy::Never
), "Warn in ARM, reject in Thumb" }
,
82 clEnumValN(ImplicitItModeTy::ARMOnly, "arm",llvm::cl::OptionEnumValue { "arm", int(ImplicitItModeTy::ARMOnly
), "Accept in ARM, reject in Thumb" }
83 "Accept in ARM, reject in Thumb")llvm::cl::OptionEnumValue { "arm", int(ImplicitItModeTy::ARMOnly
), "Accept in ARM, reject in Thumb" }
,
84 clEnumValN(ImplicitItModeTy::ThumbOnly, "thumb",llvm::cl::OptionEnumValue { "thumb", int(ImplicitItModeTy::ThumbOnly
), "Warn in ARM, emit implicit ITs in Thumb" }
85 "Warn in ARM, emit implicit ITs in Thumb")llvm::cl::OptionEnumValue { "thumb", int(ImplicitItModeTy::ThumbOnly
), "Warn in ARM, emit implicit ITs in Thumb" }
));
86
87static cl::opt<bool> AddBuildAttributes("arm-add-build-attributes",
88 cl::init(false));
89
90enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
91
92class UnwindContext {
93 using Locs = SmallVector<SMLoc, 4>;
94
95 MCAsmParser &Parser;
96 Locs FnStartLocs;
97 Locs CantUnwindLocs;
98 Locs PersonalityLocs;
99 Locs PersonalityIndexLocs;
100 Locs HandlerDataLocs;
101 int FPReg;
102
103public:
104 UnwindContext(MCAsmParser &P) : Parser(P), FPReg(ARM::SP) {}
105
106 bool hasFnStart() const { return !FnStartLocs.empty(); }
107 bool cantUnwind() const { return !CantUnwindLocs.empty(); }
108 bool hasHandlerData() const { return !HandlerDataLocs.empty(); }
109
110 bool hasPersonality() const {
111 return !(PersonalityLocs.empty() && PersonalityIndexLocs.empty());
112 }
113
114 void recordFnStart(SMLoc L) { FnStartLocs.push_back(L); }
115 void recordCantUnwind(SMLoc L) { CantUnwindLocs.push_back(L); }
116 void recordPersonality(SMLoc L) { PersonalityLocs.push_back(L); }
117 void recordHandlerData(SMLoc L) { HandlerDataLocs.push_back(L); }
118 void recordPersonalityIndex(SMLoc L) { PersonalityIndexLocs.push_back(L); }
119
120 void saveFPReg(int Reg) { FPReg = Reg; }
121 int getFPReg() const { return FPReg; }
122
123 void emitFnStartLocNotes() const {
124 for (Locs::const_iterator FI = FnStartLocs.begin(), FE = FnStartLocs.end();
125 FI != FE; ++FI)
126 Parser.Note(*FI, ".fnstart was specified here");
127 }
128
129 void emitCantUnwindLocNotes() const {
130 for (Locs::const_iterator UI = CantUnwindLocs.begin(),
131 UE = CantUnwindLocs.end(); UI != UE; ++UI)
132 Parser.Note(*UI, ".cantunwind was specified here");
133 }
134
135 void emitHandlerDataLocNotes() const {
136 for (Locs::const_iterator HI = HandlerDataLocs.begin(),
137 HE = HandlerDataLocs.end(); HI != HE; ++HI)
138 Parser.Note(*HI, ".handlerdata was specified here");
139 }
140
141 void emitPersonalityLocNotes() const {
142 for (Locs::const_iterator PI = PersonalityLocs.begin(),
143 PE = PersonalityLocs.end(),
144 PII = PersonalityIndexLocs.begin(),
145 PIE = PersonalityIndexLocs.end();
146 PI != PE || PII != PIE;) {
147 if (PI != PE && (PII == PIE || PI->getPointer() < PII->getPointer()))
148 Parser.Note(*PI++, ".personality was specified here");
149 else if (PII != PIE && (PI == PE || PII->getPointer() < PI->getPointer()))
150 Parser.Note(*PII++, ".personalityindex was specified here");
151 else
152 llvm_unreachable(".personality and .personalityindex cannot be "::llvm::llvm_unreachable_internal(".personality and .personalityindex cannot be "
"at the same location", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 153)
153 "at the same location")::llvm::llvm_unreachable_internal(".personality and .personalityindex cannot be "
"at the same location", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 153)
;
154 }
155 }
156
157 void reset() {
158 FnStartLocs = Locs();
159 CantUnwindLocs = Locs();
160 PersonalityLocs = Locs();
161 HandlerDataLocs = Locs();
162 PersonalityIndexLocs = Locs();
163 FPReg = ARM::SP;
164 }
165};
166
167class ARMAsmParser : public MCTargetAsmParser {
168 const MCRegisterInfo *MRI;
169 UnwindContext UC;
170
171 ARMTargetStreamer &getTargetStreamer() {
172 assert(getParser().getStreamer().getTargetStreamer() &&(static_cast <bool> (getParser().getStreamer().getTargetStreamer
() && "do not have a target streamer") ? void (0) : __assert_fail
("getParser().getStreamer().getTargetStreamer() && \"do not have a target streamer\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 173, __extension__ __PRETTY_FUNCTION__))
173 "do not have a target streamer")(static_cast <bool> (getParser().getStreamer().getTargetStreamer
() && "do not have a target streamer") ? void (0) : __assert_fail
("getParser().getStreamer().getTargetStreamer() && \"do not have a target streamer\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 173, __extension__ __PRETTY_FUNCTION__))
;
174 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
175 return static_cast<ARMTargetStreamer &>(TS);
176 }
177
178 // Map of register aliases registers via the .req directive.
179 StringMap<unsigned> RegisterReqs;
180
181 bool NextSymbolIsThumb;
182
183 bool useImplicitITThumb() const {
184 return ImplicitItMode == ImplicitItModeTy::Always ||
185 ImplicitItMode == ImplicitItModeTy::ThumbOnly;
186 }
187
188 bool useImplicitITARM() const {
189 return ImplicitItMode == ImplicitItModeTy::Always ||
190 ImplicitItMode == ImplicitItModeTy::ARMOnly;
191 }
192
193 struct {
194 ARMCC::CondCodes Cond; // Condition for IT block.
195 unsigned Mask:4; // Condition mask for instructions.
196 // Starting at first 1 (from lsb).
197 // '1' condition as indicated in IT.
198 // '0' inverse of condition (else).
199 // Count of instructions in IT block is
200 // 4 - trailingzeroes(mask)
201 // Note that this does not have the same encoding
202 // as in the IT instruction, which also depends
203 // on the low bit of the condition code.
204
205 unsigned CurPosition; // Current position in parsing of IT
206 // block. In range [0,4], with 0 being the IT
207 // instruction itself. Initialized according to
208 // count of instructions in block. ~0U if no
209 // active IT block.
210
211 bool IsExplicit; // true - The IT instruction was present in the
212 // input, we should not modify it.
213 // false - The IT instruction was added
214 // implicitly, we can extend it if that
215 // would be legal.
216 } ITState;
217
218 SmallVector<MCInst, 4> PendingConditionalInsts;
219
220 void flushPendingInstructions(MCStreamer &Out) override {
221 if (!inImplicitITBlock()) {
222 assert(PendingConditionalInsts.size() == 0)(static_cast <bool> (PendingConditionalInsts.size() == 0
) ? void (0) : __assert_fail ("PendingConditionalInsts.size() == 0"
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 222, __extension__ __PRETTY_FUNCTION__))
;
223 return;
224 }
225
226 // Emit the IT instruction
227 unsigned Mask = getITMaskEncoding();
228 MCInst ITInst;
229 ITInst.setOpcode(ARM::t2IT);
230 ITInst.addOperand(MCOperand::createImm(ITState.Cond));
231 ITInst.addOperand(MCOperand::createImm(Mask));
232 Out.EmitInstruction(ITInst, getSTI());
233
234 // Emit the conditonal instructions
235 assert(PendingConditionalInsts.size() <= 4)(static_cast <bool> (PendingConditionalInsts.size() <=
4) ? void (0) : __assert_fail ("PendingConditionalInsts.size() <= 4"
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 235, __extension__ __PRETTY_FUNCTION__))
;
236 for (const MCInst &Inst : PendingConditionalInsts) {
237 Out.EmitInstruction(Inst, getSTI());
238 }
239 PendingConditionalInsts.clear();
240
241 // Clear the IT state
242 ITState.Mask = 0;
243 ITState.CurPosition = ~0U;
244 }
245
246 bool inITBlock() { return ITState.CurPosition != ~0U; }
247 bool inExplicitITBlock() { return inITBlock() && ITState.IsExplicit; }
248 bool inImplicitITBlock() { return inITBlock() && !ITState.IsExplicit; }
249
250 bool lastInITBlock() {
251 return ITState.CurPosition == 4 - countTrailingZeros(ITState.Mask);
252 }
253
254 void forwardITPosition() {
255 if (!inITBlock()) return;
256 // Move to the next instruction in the IT block, if there is one. If not,
257 // mark the block as done, except for implicit IT blocks, which we leave
258 // open until we find an instruction that can't be added to it.
259 unsigned TZ = countTrailingZeros(ITState.Mask);
260 if (++ITState.CurPosition == 5 - TZ && ITState.IsExplicit)
261 ITState.CurPosition = ~0U; // Done with the IT block after this.
262 }
263
264 // Rewind the state of the current IT block, removing the last slot from it.
265 void rewindImplicitITPosition() {
266 assert(inImplicitITBlock())(static_cast <bool> (inImplicitITBlock()) ? void (0) : __assert_fail
("inImplicitITBlock()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 266, __extension__ __PRETTY_FUNCTION__))
;
267 assert(ITState.CurPosition > 1)(static_cast <bool> (ITState.CurPosition > 1) ? void
(0) : __assert_fail ("ITState.CurPosition > 1", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 267, __extension__ __PRETTY_FUNCTION__))
;
268 ITState.CurPosition--;
269 unsigned TZ = countTrailingZeros(ITState.Mask);
270 unsigned NewMask = 0;
271 NewMask |= ITState.Mask & (0xC << TZ);
7
The result of the left shift is undefined due to shifting by '32', which is greater or equal to the width of type 'int'
272 NewMask |= 0x2 << TZ;
273 ITState.Mask = NewMask;
274 }
275
276 // Rewind the state of the current IT block, removing the last slot from it.
277 // If we were at the first slot, this closes the IT block.
278 void discardImplicitITBlock() {
279 assert(inImplicitITBlock())(static_cast <bool> (inImplicitITBlock()) ? void (0) : __assert_fail
("inImplicitITBlock()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 279, __extension__ __PRETTY_FUNCTION__))
;
280 assert(ITState.CurPosition == 1)(static_cast <bool> (ITState.CurPosition == 1) ? void (
0) : __assert_fail ("ITState.CurPosition == 1", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 280, __extension__ __PRETTY_FUNCTION__))
;
281 ITState.CurPosition = ~0U;
282 }
283
284 // Return the low-subreg of a given Q register.
285 unsigned getDRegFromQReg(unsigned QReg) const {
286 return MRI->getSubReg(QReg, ARM::dsub_0);
287 }
288
289 // Get the encoding of the IT mask, as it will appear in an IT instruction.
290 unsigned getITMaskEncoding() {
291 assert(inITBlock())(static_cast <bool> (inITBlock()) ? void (0) : __assert_fail
("inITBlock()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 291, __extension__ __PRETTY_FUNCTION__))
;
292 unsigned Mask = ITState.Mask;
293 unsigned TZ = countTrailingZeros(Mask);
294 if ((ITState.Cond & 1) == 0) {
295 assert(Mask && TZ <= 3 && "illegal IT mask value!")(static_cast <bool> (Mask && TZ <= 3 &&
"illegal IT mask value!") ? void (0) : __assert_fail ("Mask && TZ <= 3 && \"illegal IT mask value!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 295, __extension__ __PRETTY_FUNCTION__))
;
296 Mask ^= (0xE << TZ) & 0xF;
297 }
298 return Mask;
299 }
300
301 // Get the condition code corresponding to the current IT block slot.
302 ARMCC::CondCodes currentITCond() {
303 unsigned MaskBit;
304 if (ITState.CurPosition == 1)
305 MaskBit = 1;
306 else
307 MaskBit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
308
309 return MaskBit ? ITState.Cond : ARMCC::getOppositeCondition(ITState.Cond);
310 }
311
312 // Invert the condition of the current IT block slot without changing any
313 // other slots in the same block.
314 void invertCurrentITCondition() {
315 if (ITState.CurPosition == 1) {
316 ITState.Cond = ARMCC::getOppositeCondition(ITState.Cond);
317 } else {
318 ITState.Mask ^= 1 << (5 - ITState.CurPosition);
319 }
320 }
321
322 // Returns true if the current IT block is full (all 4 slots used).
323 bool isITBlockFull() {
324 return inITBlock() && (ITState.Mask & 1);
325 }
326
327 // Extend the current implicit IT block to have one more slot with the given
328 // condition code.
329 void extendImplicitITBlock(ARMCC::CondCodes Cond) {
330 assert(inImplicitITBlock())(static_cast <bool> (inImplicitITBlock()) ? void (0) : __assert_fail
("inImplicitITBlock()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 330, __extension__ __PRETTY_FUNCTION__))
;
331 assert(!isITBlockFull())(static_cast <bool> (!isITBlockFull()) ? void (0) : __assert_fail
("!isITBlockFull()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 331, __extension__ __PRETTY_FUNCTION__))
;
332 assert(Cond == ITState.Cond ||(static_cast <bool> (Cond == ITState.Cond || Cond == ARMCC
::getOppositeCondition(ITState.Cond)) ? void (0) : __assert_fail
("Cond == ITState.Cond || Cond == ARMCC::getOppositeCondition(ITState.Cond)"
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 333, __extension__ __PRETTY_FUNCTION__))
333 Cond == ARMCC::getOppositeCondition(ITState.Cond))(static_cast <bool> (Cond == ITState.Cond || Cond == ARMCC
::getOppositeCondition(ITState.Cond)) ? void (0) : __assert_fail
("Cond == ITState.Cond || Cond == ARMCC::getOppositeCondition(ITState.Cond)"
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 333, __extension__ __PRETTY_FUNCTION__))
;
334 unsigned TZ = countTrailingZeros(ITState.Mask);
335 unsigned NewMask = 0;
336 // Keep any existing condition bits.
337 NewMask |= ITState.Mask & (0xE << TZ);
338 // Insert the new condition bit.
339 NewMask |= (Cond == ITState.Cond) << TZ;
340 // Move the trailing 1 down one bit.
341 NewMask |= 1 << (TZ - 1);
342 ITState.Mask = NewMask;
343 }
344
345 // Create a new implicit IT block with a dummy condition code.
346 void startImplicitITBlock() {
347 assert(!inITBlock())(static_cast <bool> (!inITBlock()) ? void (0) : __assert_fail
("!inITBlock()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 347, __extension__ __PRETTY_FUNCTION__))
;
348 ITState.Cond = ARMCC::AL;
349 ITState.Mask = 8;
350 ITState.CurPosition = 1;
351 ITState.IsExplicit = false;
352 }
353
354 // Create a new explicit IT block with the given condition and mask. The mask
355 // should be in the parsed format, with a 1 implying 't', regardless of the
356 // low bit of the condition.
357 void startExplicitITBlock(ARMCC::CondCodes Cond, unsigned Mask) {
358 assert(!inITBlock())(static_cast <bool> (!inITBlock()) ? void (0) : __assert_fail
("!inITBlock()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 358, __extension__ __PRETTY_FUNCTION__))
;
359 ITState.Cond = Cond;
360 ITState.Mask = Mask;
361 ITState.CurPosition = 0;
362 ITState.IsExplicit = true;
363 }
364
365 void Note(SMLoc L, const Twine &Msg, SMRange Range = None) {
366 return getParser().Note(L, Msg, Range);
367 }
368
369 bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) {
370 return getParser().Warning(L, Msg, Range);
371 }
372
373 bool Error(SMLoc L, const Twine &Msg, SMRange Range = None) {
374 return getParser().Error(L, Msg, Range);
375 }
376
377 bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands,
378 unsigned ListNo, bool IsARPop = false);
379 bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands,
380 unsigned ListNo);
381
382 int tryParseRegister();
383 bool tryParseRegisterWithWriteBack(OperandVector &);
384 int tryParseShiftRegister(OperandVector &);
385 bool parseRegisterList(OperandVector &);
386 bool parseMemory(OperandVector &);
387 bool parseOperand(OperandVector &, StringRef Mnemonic);
388 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
389 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
390 unsigned &ShiftAmount);
391 bool parseLiteralValues(unsigned Size, SMLoc L);
392 bool parseDirectiveThumb(SMLoc L);
393 bool parseDirectiveARM(SMLoc L);
394 bool parseDirectiveThumbFunc(SMLoc L);
395 bool parseDirectiveCode(SMLoc L);
396 bool parseDirectiveSyntax(SMLoc L);
397 bool parseDirectiveReq(StringRef Name, SMLoc L);
398 bool parseDirectiveUnreq(SMLoc L);
399 bool parseDirectiveArch(SMLoc L);
400 bool parseDirectiveEabiAttr(SMLoc L);
401 bool parseDirectiveCPU(SMLoc L);
402 bool parseDirectiveFPU(SMLoc L);
403 bool parseDirectiveFnStart(SMLoc L);
404 bool parseDirectiveFnEnd(SMLoc L);
405 bool parseDirectiveCantUnwind(SMLoc L);
406 bool parseDirectivePersonality(SMLoc L);
407 bool parseDirectiveHandlerData(SMLoc L);
408 bool parseDirectiveSetFP(SMLoc L);
409 bool parseDirectivePad(SMLoc L);
410 bool parseDirectiveRegSave(SMLoc L, bool IsVector);
411 bool parseDirectiveInst(SMLoc L, char Suffix = '\0');
412 bool parseDirectiveLtorg(SMLoc L);
413 bool parseDirectiveEven(SMLoc L);
414 bool parseDirectivePersonalityIndex(SMLoc L);
415 bool parseDirectiveUnwindRaw(SMLoc L);
416 bool parseDirectiveTLSDescSeq(SMLoc L);
417 bool parseDirectiveMovSP(SMLoc L);
418 bool parseDirectiveObjectArch(SMLoc L);
419 bool parseDirectiveArchExtension(SMLoc L);
420 bool parseDirectiveAlign(SMLoc L);
421 bool parseDirectiveThumbSet(SMLoc L);
422
423 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
424 bool &CarrySetting, unsigned &ProcessorIMod,
425 StringRef &ITMask);
426 void getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst,
427 bool &CanAcceptCarrySet,
428 bool &CanAcceptPredicationCode);
429
430 void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting,
431 OperandVector &Operands);
432 bool isThumb() const {
433 // FIXME: Can tablegen auto-generate this?
434 return getSTI().getFeatureBits()[ARM::ModeThumb];
435 }
436
437 bool isThumbOne() const {
438 return isThumb() && !getSTI().getFeatureBits()[ARM::FeatureThumb2];
439 }
440
441 bool isThumbTwo() const {
442 return isThumb() && getSTI().getFeatureBits()[ARM::FeatureThumb2];
443 }
444
445 bool hasThumb() const {
446 return getSTI().getFeatureBits()[ARM::HasV4TOps];
447 }
448
449 bool hasThumb2() const {
450 return getSTI().getFeatureBits()[ARM::FeatureThumb2];
451 }
452
453 bool hasV6Ops() const {
454 return getSTI().getFeatureBits()[ARM::HasV6Ops];
455 }
456
457 bool hasV6T2Ops() const {
458 return getSTI().getFeatureBits()[ARM::HasV6T2Ops];
459 }
460
461 bool hasV6MOps() const {
462 return getSTI().getFeatureBits()[ARM::HasV6MOps];
463 }
464
465 bool hasV7Ops() const {
466 return getSTI().getFeatureBits()[ARM::HasV7Ops];
467 }
468
469 bool hasV8Ops() const {
470 return getSTI().getFeatureBits()[ARM::HasV8Ops];
471 }
472
473 bool hasV8MBaseline() const {
474 return getSTI().getFeatureBits()[ARM::HasV8MBaselineOps];
475 }
476
477 bool hasV8MMainline() const {
478 return getSTI().getFeatureBits()[ARM::HasV8MMainlineOps];
479 }
480
481 bool has8MSecExt() const {
482 return getSTI().getFeatureBits()[ARM::Feature8MSecExt];
483 }
484
485 bool hasARM() const {
486 return !getSTI().getFeatureBits()[ARM::FeatureNoARM];
487 }
488
489 bool hasDSP() const {
490 return getSTI().getFeatureBits()[ARM::FeatureDSP];
491 }
492
493 bool hasD16() const {
494 return getSTI().getFeatureBits()[ARM::FeatureD16];
495 }
496
497 bool hasV8_1aOps() const {
498 return getSTI().getFeatureBits()[ARM::HasV8_1aOps];
499 }
500
501 bool hasRAS() const {
502 return getSTI().getFeatureBits()[ARM::FeatureRAS];
503 }
504
505 void SwitchMode() {
506 MCSubtargetInfo &STI = copySTI();
507 uint64_t FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
508 setAvailableFeatures(FB);
509 }
510
511 void FixModeAfterArchChange(bool WasThumb, SMLoc Loc);
512
513 bool isMClass() const {
514 return getSTI().getFeatureBits()[ARM::FeatureMClass];
515 }
516
517 /// @name Auto-generated Match Functions
518 /// {
519
520#define GET_ASSEMBLER_HEADER
521#include "ARMGenAsmMatcher.inc"
522
523 /// }
524
525 OperandMatchResultTy parseITCondCode(OperandVector &);
526 OperandMatchResultTy parseCoprocNumOperand(OperandVector &);
527 OperandMatchResultTy parseCoprocRegOperand(OperandVector &);
528 OperandMatchResultTy parseCoprocOptionOperand(OperandVector &);
529 OperandMatchResultTy parseMemBarrierOptOperand(OperandVector &);
530 OperandMatchResultTy parseInstSyncBarrierOptOperand(OperandVector &);
531 OperandMatchResultTy parseProcIFlagsOperand(OperandVector &);
532 OperandMatchResultTy parseMSRMaskOperand(OperandVector &);
533 OperandMatchResultTy parseBankedRegOperand(OperandVector &);
534 OperandMatchResultTy parsePKHImm(OperandVector &O, StringRef Op, int Low,
535 int High);
536 OperandMatchResultTy parsePKHLSLImm(OperandVector &O) {
537 return parsePKHImm(O, "lsl", 0, 31);
538 }
539 OperandMatchResultTy parsePKHASRImm(OperandVector &O) {
540 return parsePKHImm(O, "asr", 1, 32);
541 }
542 OperandMatchResultTy parseSetEndImm(OperandVector &);
543 OperandMatchResultTy parseShifterImm(OperandVector &);
544 OperandMatchResultTy parseRotImm(OperandVector &);
545 OperandMatchResultTy parseModImm(OperandVector &);
546 OperandMatchResultTy parseBitfield(OperandVector &);
547 OperandMatchResultTy parsePostIdxReg(OperandVector &);
548 OperandMatchResultTy parseAM3Offset(OperandVector &);
549 OperandMatchResultTy parseFPImm(OperandVector &);
550 OperandMatchResultTy parseVectorList(OperandVector &);
551 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index,
552 SMLoc &EndLoc);
553
554 // Asm Match Converter Methods
555 void cvtThumbMultiply(MCInst &Inst, const OperandVector &);
556 void cvtThumbBranches(MCInst &Inst, const OperandVector &);
557
558 bool validateInstruction(MCInst &Inst, const OperandVector &Ops);
559 bool processInstruction(MCInst &Inst, const OperandVector &Ops, MCStreamer &Out);
560 bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands);
561 bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands);
562 bool isITBlockTerminator(MCInst &Inst) const;
563 void fixupGNULDRDAlias(StringRef Mnemonic, OperandVector &Operands);
564
565public:
566 enum ARMMatchResultTy {
567 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
568 Match_RequiresNotITBlock,
569 Match_RequiresV6,
570 Match_RequiresThumb2,
571 Match_RequiresV8,
572 Match_RequiresFlagSetting,
573#define GET_OPERAND_DIAGNOSTIC_TYPES
574#include "ARMGenAsmMatcher.inc"
575
576 };
577
578 ARMAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
579 const MCInstrInfo &MII, const MCTargetOptions &Options)
580 : MCTargetAsmParser(Options, STI, MII), UC(Parser) {
581 MCAsmParserExtension::Initialize(Parser);
582
583 // Cache the MCRegisterInfo.
584 MRI = getContext().getRegisterInfo();
585
586 // Initialize the set of available features.
587 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
588
589 // Add build attributes based on the selected target.
590 if (AddBuildAttributes)
591 getTargetStreamer().emitTargetAttributes(STI);
592
593 // Not in an ITBlock to start with.
594 ITState.CurPosition = ~0U;
595
596 NextSymbolIsThumb = false;
597 }
598
599 // Implementation of the MCTargetAsmParser interface:
600 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
601 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
602 SMLoc NameLoc, OperandVector &Operands) override;
603 bool ParseDirective(AsmToken DirectiveID) override;
604
605 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
606 unsigned Kind) override;
607 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
608
609 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
610 OperandVector &Operands, MCStreamer &Out,
611 uint64_t &ErrorInfo,
612 bool MatchingInlineAsm) override;
613 unsigned MatchInstruction(OperandVector &Operands, MCInst &Inst,
614 SmallVectorImpl<NearMissInfo> &NearMisses,
615 bool MatchingInlineAsm, bool &EmitInITBlock,
616 MCStreamer &Out);
617
618 struct NearMissMessage {
619 SMLoc Loc;
620 SmallString<128> Message;
621 };
622
623 const char *getCustomOperandDiag(ARMMatchResultTy MatchError);
624
625 void FilterNearMisses(SmallVectorImpl<NearMissInfo> &NearMissesIn,
626 SmallVectorImpl<NearMissMessage> &NearMissesOut,
627 SMLoc IDLoc, OperandVector &Operands);
628 void ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses, SMLoc IDLoc,
629 OperandVector &Operands);
630
631 void onLabelParsed(MCSymbol *Symbol) override;
632};
633
634/// ARMOperand - Instances of this class represent a parsed ARM machine
635/// operand.
636class ARMOperand : public MCParsedAsmOperand {
637 enum KindTy {
638 k_CondCode,
639 k_CCOut,
640 k_ITCondMask,
641 k_CoprocNum,
642 k_CoprocReg,
643 k_CoprocOption,
644 k_Immediate,
645 k_MemBarrierOpt,
646 k_InstSyncBarrierOpt,
647 k_Memory,
648 k_PostIndexRegister,
649 k_MSRMask,
650 k_BankedReg,
651 k_ProcIFlags,
652 k_VectorIndex,
653 k_Register,
654 k_RegisterList,
655 k_DPRRegisterList,
656 k_SPRRegisterList,
657 k_VectorList,
658 k_VectorListAllLanes,
659 k_VectorListIndexed,
660 k_ShiftedRegister,
661 k_ShiftedImmediate,
662 k_ShifterImmediate,
663 k_RotateImmediate,
664 k_ModifiedImmediate,
665 k_ConstantPoolImmediate,
666 k_BitfieldDescriptor,
667 k_Token,
668 } Kind;
669
670 SMLoc StartLoc, EndLoc, AlignmentLoc;
671 SmallVector<unsigned, 8> Registers;
672
673 struct CCOp {
674 ARMCC::CondCodes Val;
675 };
676
677 struct CopOp {
678 unsigned Val;
679 };
680
681 struct CoprocOptionOp {
682 unsigned Val;
683 };
684
685 struct ITMaskOp {
686 unsigned Mask:4;
687 };
688
689 struct MBOptOp {
690 ARM_MB::MemBOpt Val;
691 };
692
693 struct ISBOptOp {
694 ARM_ISB::InstSyncBOpt Val;
695 };
696
697 struct IFlagsOp {
698 ARM_PROC::IFlags Val;
699 };
700
701 struct MMaskOp {
702 unsigned Val;
703 };
704
705 struct BankedRegOp {
706 unsigned Val;
707 };
708
709 struct TokOp {
710 const char *Data;
711 unsigned Length;
712 };
713
714 struct RegOp {
715 unsigned RegNum;
716 };
717
718 // A vector register list is a sequential list of 1 to 4 registers.
719 struct VectorListOp {
720 unsigned RegNum;
721 unsigned Count;
722 unsigned LaneIndex;
723 bool isDoubleSpaced;
724 };
725
726 struct VectorIndexOp {
727 unsigned Val;
728 };
729
730 struct ImmOp {
731 const MCExpr *Val;
732 };
733
734 /// Combined record for all forms of ARM address expressions.
735 struct MemoryOp {
736 unsigned BaseRegNum;
737 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
738 // was specified.
739 const MCConstantExpr *OffsetImm; // Offset immediate value
740 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
741 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
742 unsigned ShiftImm; // shift for OffsetReg.
743 unsigned Alignment; // 0 = no alignment specified
744 // n = alignment in bytes (2, 4, 8, 16, or 32)
745 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
746 };
747
748 struct PostIdxRegOp {
749 unsigned RegNum;
750 bool isAdd;
751 ARM_AM::ShiftOpc ShiftTy;
752 unsigned ShiftImm;
753 };
754
755 struct ShifterImmOp {
756 bool isASR;
757 unsigned Imm;
758 };
759
760 struct RegShiftedRegOp {
761 ARM_AM::ShiftOpc ShiftTy;
762 unsigned SrcReg;
763 unsigned ShiftReg;
764 unsigned ShiftImm;
765 };
766
767 struct RegShiftedImmOp {
768 ARM_AM::ShiftOpc ShiftTy;
769 unsigned SrcReg;
770 unsigned ShiftImm;
771 };
772
773 struct RotImmOp {
774 unsigned Imm;
775 };
776
777 struct ModImmOp {
778 unsigned Bits;
779 unsigned Rot;
780 };
781
782 struct BitfieldOp {
783 unsigned LSB;
784 unsigned Width;
785 };
786
787 union {
788 struct CCOp CC;
789 struct CopOp Cop;
790 struct CoprocOptionOp CoprocOption;
791 struct MBOptOp MBOpt;
792 struct ISBOptOp ISBOpt;
793 struct ITMaskOp ITMask;
794 struct IFlagsOp IFlags;
795 struct MMaskOp MMask;
796 struct BankedRegOp BankedReg;
797 struct TokOp Tok;
798 struct RegOp Reg;
799 struct VectorListOp VectorList;
800 struct VectorIndexOp VectorIndex;
801 struct ImmOp Imm;
802 struct MemoryOp Memory;
803 struct PostIdxRegOp PostIdxReg;
804 struct ShifterImmOp ShifterImm;
805 struct RegShiftedRegOp RegShiftedReg;
806 struct RegShiftedImmOp RegShiftedImm;
807 struct RotImmOp RotImm;
808 struct ModImmOp ModImm;
809 struct BitfieldOp Bitfield;
810 };
811
812public:
813 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
814
815 /// getStartLoc - Get the location of the first token of this operand.
816 SMLoc getStartLoc() const override { return StartLoc; }
817
818 /// getEndLoc - Get the location of the last token of this operand.
819 SMLoc getEndLoc() const override { return EndLoc; }
820
821 /// getLocRange - Get the range between the first and last token of this
822 /// operand.
823 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
824
825 /// getAlignmentLoc - Get the location of the Alignment token of this operand.
826 SMLoc getAlignmentLoc() const {
827 assert(Kind == k_Memory && "Invalid access!")(static_cast <bool> (Kind == k_Memory && "Invalid access!"
) ? void (0) : __assert_fail ("Kind == k_Memory && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 827, __extension__ __PRETTY_FUNCTION__))
;
828 return AlignmentLoc;
829 }
830
831 ARMCC::CondCodes getCondCode() const {
832 assert(Kind == k_CondCode && "Invalid access!")(static_cast <bool> (Kind == k_CondCode && "Invalid access!"
) ? void (0) : __assert_fail ("Kind == k_CondCode && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 832, __extension__ __PRETTY_FUNCTION__))
;
833 return CC.Val;
834 }
835
836 unsigned getCoproc() const {
837 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!")(static_cast <bool> ((Kind == k_CoprocNum || Kind == k_CoprocReg
) && "Invalid access!") ? void (0) : __assert_fail ("(Kind == k_CoprocNum || Kind == k_CoprocReg) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 837, __extension__ __PRETTY_FUNCTION__))
;
838 return Cop.Val;
839 }
840
841 StringRef getToken() const {
842 assert(Kind == k_Token && "Invalid access!")(static_cast <bool> (Kind == k_Token && "Invalid access!"
) ? void (0) : __assert_fail ("Kind == k_Token && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 842, __extension__ __PRETTY_FUNCTION__))
;
843 return StringRef(Tok.Data, Tok.Length);
844 }
845
846 unsigned getReg() const override {
847 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!")(static_cast <bool> ((Kind == k_Register || Kind == k_CCOut
) && "Invalid access!") ? void (0) : __assert_fail ("(Kind == k_Register || Kind == k_CCOut) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 847, __extension__ __PRETTY_FUNCTION__))
;
848 return Reg.RegNum;
849 }
850
851 const SmallVectorImpl<unsigned> &getRegList() const {
852 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||(static_cast <bool> ((Kind == k_RegisterList || Kind ==
k_DPRRegisterList || Kind == k_SPRRegisterList) && "Invalid access!"
) ? void (0) : __assert_fail ("(Kind == k_RegisterList || Kind == k_DPRRegisterList || Kind == k_SPRRegisterList) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 853, __extension__ __PRETTY_FUNCTION__))
853 Kind == k_SPRRegisterList) && "Invalid access!")(static_cast <bool> ((Kind == k_RegisterList || Kind ==
k_DPRRegisterList || Kind == k_SPRRegisterList) && "Invalid access!"
) ? void (0) : __assert_fail ("(Kind == k_RegisterList || Kind == k_DPRRegisterList || Kind == k_SPRRegisterList) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 853, __extension__ __PRETTY_FUNCTION__))
;
854 return Registers;
855 }
856
857 const MCExpr *getImm() const {
858 assert(isImm() && "Invalid access!")(static_cast <bool> (isImm() && "Invalid access!"
) ? void (0) : __assert_fail ("isImm() && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 858, __extension__ __PRETTY_FUNCTION__))
;
859 return Imm.Val;
860 }
861
862 const MCExpr *getConstantPoolImm() const {
863 assert(isConstantPoolImm() && "Invalid access!")(static_cast <bool> (isConstantPoolImm() && "Invalid access!"
) ? void (0) : __assert_fail ("isConstantPoolImm() && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 863, __extension__ __PRETTY_FUNCTION__))
;
864 return Imm.Val;
865 }
866
867 unsigned getVectorIndex() const {
868 assert(Kind == k_VectorIndex && "Invalid access!")(static_cast <bool> (Kind == k_VectorIndex && "Invalid access!"
) ? void (0) : __assert_fail ("Kind == k_VectorIndex && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 868, __extension__ __PRETTY_FUNCTION__))
;
869 return VectorIndex.Val;
870 }
871
872 ARM_MB::MemBOpt getMemBarrierOpt() const {
873 assert(Kind == k_MemBarrierOpt && "Invalid access!")(static_cast <bool> (Kind == k_MemBarrierOpt &&
"Invalid access!") ? void (0) : __assert_fail ("Kind == k_MemBarrierOpt && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 873, __extension__ __PRETTY_FUNCTION__))
;
874 return MBOpt.Val;
875 }
876
877 ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const {
878 assert(Kind == k_InstSyncBarrierOpt && "Invalid access!")(static_cast <bool> (Kind == k_InstSyncBarrierOpt &&
"Invalid access!") ? void (0) : __assert_fail ("Kind == k_InstSyncBarrierOpt && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 878, __extension__ __PRETTY_FUNCTION__))
;
879 return ISBOpt.Val;
880 }
881
882 ARM_PROC::IFlags getProcIFlags() const {
883 assert(Kind == k_ProcIFlags && "Invalid access!")(static_cast <bool> (Kind == k_ProcIFlags && "Invalid access!"
) ? void (0) : __assert_fail ("Kind == k_ProcIFlags && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 883, __extension__ __PRETTY_FUNCTION__))
;
884 return IFlags.Val;
885 }
886
887 unsigned getMSRMask() const {
888 assert(Kind == k_MSRMask && "Invalid access!")(static_cast <bool> (Kind == k_MSRMask && "Invalid access!"
) ? void (0) : __assert_fail ("Kind == k_MSRMask && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 888, __extension__ __PRETTY_FUNCTION__))
;
889 return MMask.Val;
890 }
891
892 unsigned getBankedReg() const {
893 assert(Kind == k_BankedReg && "Invalid access!")(static_cast <bool> (Kind == k_BankedReg && "Invalid access!"
) ? void (0) : __assert_fail ("Kind == k_BankedReg && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 893, __extension__ __PRETTY_FUNCTION__))
;
894 return BankedReg.Val;
895 }
896
897 bool isCoprocNum() const { return Kind == k_CoprocNum; }
898 bool isCoprocReg() const { return Kind == k_CoprocReg; }
899 bool isCoprocOption() const { return Kind == k_CoprocOption; }
900 bool isCondCode() const { return Kind == k_CondCode; }
901 bool isCCOut() const { return Kind == k_CCOut; }
902 bool isITMask() const { return Kind == k_ITCondMask; }
903 bool isITCondCode() const { return Kind == k_CondCode; }
904 bool isImm() const override {
905 return Kind == k_Immediate;
906 }
907
908 bool isARMBranchTarget() const {
909 if (!isImm()) return false;
910
911 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()))
912 return CE->getValue() % 4 == 0;
913 return true;
914 }
915
916
917 bool isThumbBranchTarget() const {
918 if (!isImm()) return false;
919
920 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()))
921 return CE->getValue() % 2 == 0;
922 return true;
923 }
924
925 // checks whether this operand is an unsigned offset which fits is a field
926 // of specified width and scaled by a specific number of bits
927 template<unsigned width, unsigned scale>
928 bool isUnsignedOffset() const {
929 if (!isImm()) return false;
930 if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
931 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
932 int64_t Val = CE->getValue();
933 int64_t Align = 1LL << scale;
934 int64_t Max = Align * ((1LL << width) - 1);
935 return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max);
936 }
937 return false;
938 }
939
940 // checks whether this operand is an signed offset which fits is a field
941 // of specified width and scaled by a specific number of bits
942 template<unsigned width, unsigned scale>
943 bool isSignedOffset() const {
944 if (!isImm()) return false;
945 if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
946 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
947 int64_t Val = CE->getValue();
948 int64_t Align = 1LL << scale;
949 int64_t Max = Align * ((1LL << (width-1)) - 1);
950 int64_t Min = -Align * (1LL << (width-1));
951 return ((Val % Align) == 0) && (Val >= Min) && (Val <= Max);
952 }
953 return false;
954 }
955
956 // checks whether this operand is a memory operand computed as an offset
957 // applied to PC. the offset may have 8 bits of magnitude and is represented
958 // with two bits of shift. textually it may be either [pc, #imm], #imm or
959 // relocable expression...
960 bool isThumbMemPC() const {
961 int64_t Val = 0;
962 if (isImm()) {
963 if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
964 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val);
965 if (!CE) return false;
966 Val = CE->getValue();
967 }
968 else if (isMem()) {
969 if(!Memory.OffsetImm || Memory.OffsetRegNum) return false;
970 if(Memory.BaseRegNum != ARM::PC) return false;
971 Val = Memory.OffsetImm->getValue();
972 }
973 else return false;
974 return ((Val % 4) == 0) && (Val >= 0) && (Val <= 1020);
975 }
976
977 bool isFPImm() const {
978 if (!isImm()) return false;
979 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
980 if (!CE) return false;
981 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
982 return Val != -1;
983 }
984
985 template<int64_t N, int64_t M>
986 bool isImmediate() const {
987 if (!isImm()) return false;
988 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
989 if (!CE) return false;
990 int64_t Value = CE->getValue();
991 return Value >= N && Value <= M;
992 }
993
994 template<int64_t N, int64_t M>
995 bool isImmediateS4() const {
996 if (!isImm()) return false;
997 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
998 if (!CE) return false;
999 int64_t Value = CE->getValue();
1000 return ((Value & 3) == 0) && Value >= N && Value <= M;
1001 }
1002
1003 bool isFBits16() const {
1004 return isImmediate<0, 17>();
1005 }
1006 bool isFBits32() const {
1007 return isImmediate<1, 33>();
1008 }
1009 bool isImm8s4() const {
1010 return isImmediateS4<-1020, 1020>();
1011 }
1012 bool isImm0_1020s4() const {
1013 return isImmediateS4<0, 1020>();
1014 }
1015 bool isImm0_508s4() const {
1016 return isImmediateS4<0, 508>();
1017 }
1018 bool isImm0_508s4Neg() const {
1019 if (!isImm()) return false;
1020 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1021 if (!CE) return false;
1022 int64_t Value = -CE->getValue();
1023 // explicitly exclude zero. we want that to use the normal 0_508 version.
1024 return ((Value & 3) == 0) && Value > 0 && Value <= 508;
1025 }
1026
1027 bool isImm0_4095Neg() const {
1028 if (!isImm()) return false;
1029 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1030 if (!CE) return false;
1031 int64_t Value = -CE->getValue();
1032 return Value > 0 && Value < 4096;
1033 }
1034
1035 bool isImm0_7() const {
1036 return isImmediate<0, 7>();
1037 }
1038
1039 bool isImm1_16() const {
1040 return isImmediate<1, 16>();
1041 }
1042
1043 bool isImm1_32() const {
1044 return isImmediate<1, 32>();
1045 }
1046
1047 bool isImm8_255() const {
1048 return isImmediate<8, 255>();
1049 }
1050
1051 bool isImm256_65535Expr() const {
1052 if (!isImm()) return false;
1053 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1054 // If it's not a constant expression, it'll generate a fixup and be
1055 // handled later.
1056 if (!CE) return true;
1057 int64_t Value = CE->getValue();
1058 return Value >= 256 && Value < 65536;
1059 }
1060
1061 bool isImm0_65535Expr() const {
1062 if (!isImm()) return false;
1063 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1064 // If it's not a constant expression, it'll generate a fixup and be
1065 // handled later.
1066 if (!CE) return true;
1067 int64_t Value = CE->getValue();
1068 return Value >= 0 && Value < 65536;
1069 }
1070
1071 bool isImm24bit() const {
1072 return isImmediate<0, 0xffffff + 1>();
1073 }
1074
1075 bool isImmThumbSR() const {
1076 return isImmediate<1, 33>();
1077 }
1078
1079 bool isPKHLSLImm() const {
1080 return isImmediate<0, 32>();
1081 }
1082
1083 bool isPKHASRImm() const {
1084 return isImmediate<0, 33>();
1085 }
1086
1087 bool isAdrLabel() const {
1088 // If we have an immediate that's not a constant, treat it as a label
1089 // reference needing a fixup.
1090 if (isImm() && !isa<MCConstantExpr>(getImm()))
1091 return true;
1092
1093 // If it is a constant, it must fit into a modified immediate encoding.
1094 if (!isImm()) return false;
1095 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1096 if (!CE) return false;
1097 int64_t Value = CE->getValue();
1098 return (ARM_AM::getSOImmVal(Value) != -1 ||
1099 ARM_AM::getSOImmVal(-Value) != -1);
1100 }
1101
1102 bool isT2SOImm() const {
1103 // If we have an immediate that's not a constant, treat it as an expression
1104 // needing a fixup.
1105 if (isImm() && !isa<MCConstantExpr>(getImm())) {
1106 // We want to avoid matching :upper16: and :lower16: as we want these
1107 // expressions to match in isImm0_65535Expr()
1108 const ARMMCExpr *ARM16Expr = dyn_cast<ARMMCExpr>(getImm());
1109 return (!ARM16Expr || (ARM16Expr->getKind() != ARMMCExpr::VK_ARM_HI16 &&
1110 ARM16Expr->getKind() != ARMMCExpr::VK_ARM_LO16));
1111 }
1112 if (!isImm()) return false;
1113 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1114 if (!CE) return false;
1115 int64_t Value = CE->getValue();
1116 return ARM_AM::getT2SOImmVal(Value) != -1;
1117 }
1118
1119 bool isT2SOImmNot() const {
1120 if (!isImm()) return false;
1121 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1122 if (!CE) return false;
1123 int64_t Value = CE->getValue();
1124 return ARM_AM::getT2SOImmVal(Value) == -1 &&
1125 ARM_AM::getT2SOImmVal(~Value) != -1;
1126 }
1127
1128 bool isT2SOImmNeg() const {
1129 if (!isImm()) return false;
1130 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1131 if (!CE) return false;
1132 int64_t Value = CE->getValue();
1133 // Only use this when not representable as a plain so_imm.
1134 return ARM_AM::getT2SOImmVal(Value) == -1 &&
1135 ARM_AM::getT2SOImmVal(-Value) != -1;
1136 }
1137
1138 bool isSetEndImm() const {
1139 if (!isImm()) return false;
1140 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1141 if (!CE) return false;
1142 int64_t Value = CE->getValue();
1143 return Value == 1 || Value == 0;
1144 }
1145
1146 bool isReg() const override { return Kind == k_Register; }
1147 bool isRegList() const { return Kind == k_RegisterList; }
1148 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
1149 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
1150 bool isToken() const override { return Kind == k_Token; }
1151 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
1152 bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; }
1153 bool isMem() const override {
1154 if (Kind != k_Memory)
1155 return false;
1156 if (Memory.BaseRegNum &&
1157 !ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.BaseRegNum))
1158 return false;
1159 if (Memory.OffsetRegNum &&
1160 !ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.OffsetRegNum))
1161 return false;
1162 return true;
1163 }
1164 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
1165 bool isRegShiftedReg() const {
1166 return Kind == k_ShiftedRegister &&
1167 ARMMCRegisterClasses[ARM::GPRRegClassID].contains(
1168 RegShiftedReg.SrcReg) &&
1169 ARMMCRegisterClasses[ARM::GPRRegClassID].contains(
1170 RegShiftedReg.ShiftReg);
1171 }
1172 bool isRegShiftedImm() const {
1173 return Kind == k_ShiftedImmediate &&
1174 ARMMCRegisterClasses[ARM::GPRRegClassID].contains(
1175 RegShiftedImm.SrcReg);
1176 }
1177 bool isRotImm() const { return Kind == k_RotateImmediate; }
1178 bool isModImm() const { return Kind == k_ModifiedImmediate; }
1179
1180 bool isModImmNot() const {
1181 if (!isImm()) return false;
1182 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1183 if (!CE) return false;
1184 int64_t Value = CE->getValue();
1185 return ARM_AM::getSOImmVal(~Value) != -1;
1186 }
1187
1188 bool isModImmNeg() const {
1189 if (!isImm()) return false;
1190 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1191 if (!CE) return false;
1192 int64_t Value = CE->getValue();
1193 return ARM_AM::getSOImmVal(Value) == -1 &&
1194 ARM_AM::getSOImmVal(-Value) != -1;
1195 }
1196
1197 bool isThumbModImmNeg1_7() const {
1198 if (!isImm()) return false;
1199 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1200 if (!CE) return false;
1201 int32_t Value = -(int32_t)CE->getValue();
1202 return 0 < Value && Value < 8;
1203 }
1204
1205 bool isThumbModImmNeg8_255() const {
1206 if (!isImm()) return false;
1207 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1208 if (!CE) return false;
1209 int32_t Value = -(int32_t)CE->getValue();
1210 return 7 < Value && Value < 256;
1211 }
1212
1213 bool isConstantPoolImm() const { return Kind == k_ConstantPoolImmediate; }
1214 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
1215 bool isPostIdxRegShifted() const {
1216 return Kind == k_PostIndexRegister &&
1217 ARMMCRegisterClasses[ARM::GPRRegClassID].contains(PostIdxReg.RegNum);
1218 }
1219 bool isPostIdxReg() const {
1220 return isPostIdxRegShifted() && PostIdxReg.ShiftTy == ARM_AM::no_shift;
1221 }
1222 bool isMemNoOffset(bool alignOK = false, unsigned Alignment = 0) const {
1223 if (!isMem())
1224 return false;
1225 // No offset of any kind.
1226 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr &&
1227 (alignOK || Memory.Alignment == Alignment);
1228 }
1229 bool isMemPCRelImm12() const {
1230 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1231 return false;
1232 // Base register must be PC.
1233 if (Memory.BaseRegNum != ARM::PC)
1234 return false;
1235 // Immediate offset in range [-4095, 4095].
1236 if (!Memory.OffsetImm) return true;
1237 int64_t Val = Memory.OffsetImm->getValue();
1238 return (Val > -4096 && Val < 4096) ||
1239 (Val == std::numeric_limits<int32_t>::min());
1240 }
1241
1242 bool isAlignedMemory() const {
1243 return isMemNoOffset(true);
1244 }
1245
1246 bool isAlignedMemoryNone() const {
1247 return isMemNoOffset(false, 0);
1248 }
1249
1250 bool isDupAlignedMemoryNone() const {
1251 return isMemNoOffset(false, 0);
1252 }
1253
1254 bool isAlignedMemory16() const {
1255 if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2.
1256 return true;
1257 return isMemNoOffset(false, 0);
1258 }
1259
1260 bool isDupAlignedMemory16() const {
1261 if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2.
1262 return true;
1263 return isMemNoOffset(false, 0);
1264 }
1265
1266 bool isAlignedMemory32() const {
1267 if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4.
1268 return true;
1269 return isMemNoOffset(false, 0);
1270 }
1271
1272 bool isDupAlignedMemory32() const {
1273 if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4.
1274 return true;
1275 return isMemNoOffset(false, 0);
1276 }
1277
1278 bool isAlignedMemory64() const {
1279 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1280 return true;
1281 return isMemNoOffset(false, 0);
1282 }
1283
1284 bool isDupAlignedMemory64() const {
1285 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1286 return true;
1287 return isMemNoOffset(false, 0);
1288 }
1289
1290 bool isAlignedMemory64or128() const {
1291 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1292 return true;
1293 if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16.
1294 return true;
1295 return isMemNoOffset(false, 0);
1296 }
1297
1298 bool isDupAlignedMemory64or128() const {
1299 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1300 return true;
1301 if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16.
1302 return true;
1303 return isMemNoOffset(false, 0);
1304 }
1305
1306 bool isAlignedMemory64or128or256() const {
1307 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1308 return true;
1309 if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16.
1310 return true;
1311 if (isMemNoOffset(false, 32)) // alignment in bytes for 256-bits is 32.
1312 return true;
1313 return isMemNoOffset(false, 0);
1314 }
1315
1316 bool isAddrMode2() const {
1317 if (!isMem() || Memory.Alignment != 0) return false;
1318 // Check for register offset.
1319 if (Memory.OffsetRegNum) return true;
1320 // Immediate offset in range [-4095, 4095].
1321 if (!Memory.OffsetImm) return true;
1322 int64_t Val = Memory.OffsetImm->getValue();
1323 return Val > -4096 && Val < 4096;
1324 }
1325
1326 bool isAM2OffsetImm() const {
1327 if (!isImm()) return false;
1328 // Immediate offset in range [-4095, 4095].
1329 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1330 if (!CE) return false;
1331 int64_t Val = CE->getValue();
1332 return (Val == std::numeric_limits<int32_t>::min()) ||
1333 (Val > -4096 && Val < 4096);
1334 }
1335
1336 bool isAddrMode3() const {
1337 // If we have an immediate that's not a constant, treat it as a label
1338 // reference needing a fixup. If it is a constant, it's something else
1339 // and we reject it.
1340 if (isImm() && !isa<MCConstantExpr>(getImm()))
1341 return true;
1342 if (!isMem() || Memory.Alignment != 0) return false;
1343 // No shifts are legal for AM3.
1344 if (Memory.ShiftType != ARM_AM::no_shift) return false;
1345 // Check for register offset.
1346 if (Memory.OffsetRegNum) return true;
1347 // Immediate offset in range [-255, 255].
1348 if (!Memory.OffsetImm) return true;
1349 int64_t Val = Memory.OffsetImm->getValue();
1350 // The #-0 offset is encoded as std::numeric_limits<int32_t>::min(), and we
1351 // have to check for this too.
1352 return (Val > -256 && Val < 256) ||
1353 Val == std::numeric_limits<int32_t>::min();
1354 }
1355
1356 bool isAM3Offset() const {
1357 if (isPostIdxReg())
1358 return true;
1359 if (!isImm())
1360 return false;
1361 // Immediate offset in range [-255, 255].
1362 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1363 if (!CE) return false;
1364 int64_t Val = CE->getValue();
1365 // Special case, #-0 is std::numeric_limits<int32_t>::min().
1366 return (Val > -256 && Val < 256) ||
1367 Val == std::numeric_limits<int32_t>::min();
1368 }
1369
1370 bool isAddrMode5() const {
1371 // If we have an immediate that's not a constant, treat it as a label
1372 // reference needing a fixup. If it is a constant, it's something else
1373 // and we reject it.
1374 if (isImm() && !isa<MCConstantExpr>(getImm()))
1375 return true;
1376 if (!isMem() || Memory.Alignment != 0) return false;
1377 // Check for register offset.
1378 if (Memory.OffsetRegNum) return false;
1379 // Immediate offset in range [-1020, 1020] and a multiple of 4.
1380 if (!Memory.OffsetImm) return true;
1381 int64_t Val = Memory.OffsetImm->getValue();
1382 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
1383 Val == std::numeric_limits<int32_t>::min();
1384 }
1385
1386 bool isAddrMode5FP16() const {
1387 // If we have an immediate that's not a constant, treat it as a label
1388 // reference needing a fixup. If it is a constant, it's something else
1389 // and we reject it.
1390 if (isImm() && !isa<MCConstantExpr>(getImm()))
1391 return true;
1392 if (!isMem() || Memory.Alignment != 0) return false;
1393 // Check for register offset.
1394 if (Memory.OffsetRegNum) return false;
1395 // Immediate offset in range [-510, 510] and a multiple of 2.
1396 if (!Memory.OffsetImm) return true;
1397 int64_t Val = Memory.OffsetImm->getValue();
1398 return (Val >= -510 && Val <= 510 && ((Val & 1) == 0)) ||
1399 Val == std::numeric_limits<int32_t>::min();
1400 }
1401
1402 bool isMemTBB() const {
1403 if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
1404 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
1405 return false;
1406 return true;
1407 }
1408
1409 bool isMemTBH() const {
1410 if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
1411 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
1412 Memory.Alignment != 0 )
1413 return false;
1414 return true;
1415 }
1416
1417 bool isMemRegOffset() const {
1418 if (!isMem() || !Memory.OffsetRegNum || Memory.Alignment != 0)
1419 return false;
1420 return true;
1421 }
1422
1423 bool isT2MemRegOffset() const {
1424 if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
1425 Memory.Alignment != 0 || Memory.BaseRegNum == ARM::PC)
1426 return false;
1427 // Only lsl #{0, 1, 2, 3} allowed.
1428 if (Memory.ShiftType == ARM_AM::no_shift)
1429 return true;
1430 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
1431 return false;
1432 return true;
1433 }
1434
1435 bool isMemThumbRR() const {
1436 // Thumb reg+reg addressing is simple. Just two registers, a base and
1437 // an offset. No shifts, negations or any other complicating factors.
1438 if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
1439 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
1440 return false;
1441 return isARMLowRegister(Memory.BaseRegNum) &&
1442 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
1443 }
1444
1445 bool isMemThumbRIs4() const {
1446 if (!isMem() || Memory.OffsetRegNum != 0 ||
1447 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
1448 return false;
1449 // Immediate offset, multiple of 4 in range [0, 124].
1450 if (!Memory.OffsetImm) return true;
1451 int64_t Val = Memory.OffsetImm->getValue();
1452 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
1453 }
1454
1455 bool isMemThumbRIs2() const {
1456 if (!isMem() || Memory.OffsetRegNum != 0 ||
1457 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
1458 return false;
1459 // Immediate offset, multiple of 4 in range [0, 62].
1460 if (!Memory.OffsetImm) return true;
1461 int64_t Val = Memory.OffsetImm->getValue();
1462 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1463 }
1464
1465 bool isMemThumbRIs1() const {
1466 if (!isMem() || Memory.OffsetRegNum != 0 ||
1467 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
1468 return false;
1469 // Immediate offset in range [0, 31].
1470 if (!Memory.OffsetImm) return true;
1471 int64_t Val = Memory.OffsetImm->getValue();
1472 return Val >= 0 && Val <= 31;
1473 }
1474
1475 bool isMemThumbSPI() const {
1476 if (!isMem() || Memory.OffsetRegNum != 0 ||
1477 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
1478 return false;
1479 // Immediate offset, multiple of 4 in range [0, 1020].
1480 if (!Memory.OffsetImm) return true;
1481 int64_t Val = Memory.OffsetImm->getValue();
1482 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
1483 }
1484
1485 bool isMemImm8s4Offset() const {
1486 // If we have an immediate that's not a constant, treat it as a label
1487 // reference needing a fixup. If it is a constant, it's something else
1488 // and we reject it.
1489 if (isImm() && !isa<MCConstantExpr>(getImm()))
1490 return true;
1491 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1492 return false;
1493 // Immediate offset a multiple of 4 in range [-1020, 1020].
1494 if (!Memory.OffsetImm) return true;
1495 int64_t Val = Memory.OffsetImm->getValue();
1496 // Special case, #-0 is std::numeric_limits<int32_t>::min().
1497 return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) ||
1498 Val == std::numeric_limits<int32_t>::min();
1499 }
1500
1501 bool isMemImm0_1020s4Offset() const {
1502 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1503 return false;
1504 // Immediate offset a multiple of 4 in range [0, 1020].
1505 if (!Memory.OffsetImm) return true;
1506 int64_t Val = Memory.OffsetImm->getValue();
1507 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1508 }
1509
1510 bool isMemImm8Offset() const {
1511 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1512 return false;
1513 // Base reg of PC isn't allowed for these encodings.
1514 if (Memory.BaseRegNum == ARM::PC) return false;
1515 // Immediate offset in range [-255, 255].
1516 if (!Memory.OffsetImm) return true;
1517 int64_t Val = Memory.OffsetImm->getValue();
1518 return (Val == std::numeric_limits<int32_t>::min()) ||
1519 (Val > -256 && Val < 256);
1520 }
1521
1522 bool isMemPosImm8Offset() const {
1523 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1524 return false;
1525 // Immediate offset in range [0, 255].
1526 if (!Memory.OffsetImm) return true;
1527 int64_t Val = Memory.OffsetImm->getValue();
1528 return Val >= 0 && Val < 256;
1529 }
1530
1531 bool isMemNegImm8Offset() const {
1532 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1533 return false;
1534 // Base reg of PC isn't allowed for these encodings.
1535 if (Memory.BaseRegNum == ARM::PC) return false;
1536 // Immediate offset in range [-255, -1].
1537 if (!Memory.OffsetImm) return false;
1538 int64_t Val = Memory.OffsetImm->getValue();
1539 return (Val == std::numeric_limits<int32_t>::min()) ||
1540 (Val > -256 && Val < 0);
1541 }
1542
1543 bool isMemUImm12Offset() const {
1544 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1545 return false;
1546 // Immediate offset in range [0, 4095].
1547 if (!Memory.OffsetImm) return true;
1548 int64_t Val = Memory.OffsetImm->getValue();
1549 return (Val >= 0 && Val < 4096);
1550 }
1551
1552 bool isMemImm12Offset() const {
1553 // If we have an immediate that's not a constant, treat it as a label
1554 // reference needing a fixup. If it is a constant, it's something else
1555 // and we reject it.
1556
1557 if (isImm() && !isa<MCConstantExpr>(getImm()))
1558 return true;
1559
1560 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1561 return false;
1562 // Immediate offset in range [-4095, 4095].
1563 if (!Memory.OffsetImm) return true;
1564 int64_t Val = Memory.OffsetImm->getValue();
1565 return (Val > -4096 && Val < 4096) ||
1566 (Val == std::numeric_limits<int32_t>::min());
1567 }
1568
1569 bool isConstPoolAsmImm() const {
1570 // Delay processing of Constant Pool Immediate, this will turn into
1571 // a constant. Match no other operand
1572 return (isConstantPoolImm());
1573 }
1574
1575 bool isPostIdxImm8() const {
1576 if (!isImm()) return false;
1577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1578 if (!CE) return false;
1579 int64_t Val = CE->getValue();
1580 return (Val > -256 && Val < 256) ||
1581 (Val == std::numeric_limits<int32_t>::min());
1582 }
1583
1584 bool isPostIdxImm8s4() const {
1585 if (!isImm()) return false;
1586 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1587 if (!CE) return false;
1588 int64_t Val = CE->getValue();
1589 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1590 (Val == std::numeric_limits<int32_t>::min());
1591 }
1592
1593 bool isMSRMask() const { return Kind == k_MSRMask; }
1594 bool isBankedReg() const { return Kind == k_BankedReg; }
1595 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
1596
1597 // NEON operands.
1598 bool isSingleSpacedVectorList() const {
1599 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1600 }
1601
1602 bool isDoubleSpacedVectorList() const {
1603 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1604 }
1605
1606 bool isVecListOneD() const {
1607 if (!isSingleSpacedVectorList()) return false;
1608 return VectorList.Count == 1;
1609 }
1610
1611 bool isVecListDPair() const {
1612 if (!isSingleSpacedVectorList()) return false;
1613 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1614 .contains(VectorList.RegNum));
1615 }
1616
1617 bool isVecListThreeD() const {
1618 if (!isSingleSpacedVectorList()) return false;
1619 return VectorList.Count == 3;
1620 }
1621
1622 bool isVecListFourD() const {
1623 if (!isSingleSpacedVectorList()) return false;
1624 return VectorList.Count == 4;
1625 }
1626
1627 bool isVecListDPairSpaced() const {
1628 if (Kind != k_VectorList) return false;
1629 if (isSingleSpacedVectorList()) return false;
1630 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1631 .contains(VectorList.RegNum));
1632 }
1633
1634 bool isVecListThreeQ() const {
1635 if (!isDoubleSpacedVectorList()) return false;
1636 return VectorList.Count == 3;
1637 }
1638
1639 bool isVecListFourQ() const {
1640 if (!isDoubleSpacedVectorList()) return false;
1641 return VectorList.Count == 4;
1642 }
1643
1644 bool isSingleSpacedVectorAllLanes() const {
1645 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1646 }
1647
1648 bool isDoubleSpacedVectorAllLanes() const {
1649 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1650 }
1651
1652 bool isVecListOneDAllLanes() const {
1653 if (!isSingleSpacedVectorAllLanes()) return false;
1654 return VectorList.Count == 1;
1655 }
1656
1657 bool isVecListDPairAllLanes() const {
1658 if (!isSingleSpacedVectorAllLanes()) return false;
1659 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1660 .contains(VectorList.RegNum));
1661 }
1662
1663 bool isVecListDPairSpacedAllLanes() const {
1664 if (!isDoubleSpacedVectorAllLanes()) return false;
1665 return VectorList.Count == 2;
1666 }
1667
1668 bool isVecListThreeDAllLanes() const {
1669 if (!isSingleSpacedVectorAllLanes()) return false;
1670 return VectorList.Count == 3;
1671 }
1672
1673 bool isVecListThreeQAllLanes() const {
1674 if (!isDoubleSpacedVectorAllLanes()) return false;
1675 return VectorList.Count == 3;
1676 }
1677
1678 bool isVecListFourDAllLanes() const {
1679 if (!isSingleSpacedVectorAllLanes()) return false;
1680 return VectorList.Count == 4;
1681 }
1682
1683 bool isVecListFourQAllLanes() const {
1684 if (!isDoubleSpacedVectorAllLanes()) return false;
1685 return VectorList.Count == 4;
1686 }
1687
1688 bool isSingleSpacedVectorIndexed() const {
1689 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1690 }
1691
1692 bool isDoubleSpacedVectorIndexed() const {
1693 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1694 }
1695
1696 bool isVecListOneDByteIndexed() const {
1697 if (!isSingleSpacedVectorIndexed()) return false;
1698 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1699 }
1700
1701 bool isVecListOneDHWordIndexed() const {
1702 if (!isSingleSpacedVectorIndexed()) return false;
1703 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1704 }
1705
1706 bool isVecListOneDWordIndexed() const {
1707 if (!isSingleSpacedVectorIndexed()) return false;
1708 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1709 }
1710
1711 bool isVecListTwoDByteIndexed() const {
1712 if (!isSingleSpacedVectorIndexed()) return false;
1713 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1714 }
1715
1716 bool isVecListTwoDHWordIndexed() const {
1717 if (!isSingleSpacedVectorIndexed()) return false;
1718 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1719 }
1720
1721 bool isVecListTwoQWordIndexed() const {
1722 if (!isDoubleSpacedVectorIndexed()) return false;
1723 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1724 }
1725
1726 bool isVecListTwoQHWordIndexed() const {
1727 if (!isDoubleSpacedVectorIndexed()) return false;
1728 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1729 }
1730
1731 bool isVecListTwoDWordIndexed() const {
1732 if (!isSingleSpacedVectorIndexed()) return false;
1733 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1734 }
1735
1736 bool isVecListThreeDByteIndexed() const {
1737 if (!isSingleSpacedVectorIndexed()) return false;
1738 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1739 }
1740
1741 bool isVecListThreeDHWordIndexed() const {
1742 if (!isSingleSpacedVectorIndexed()) return false;
1743 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1744 }
1745
1746 bool isVecListThreeQWordIndexed() const {
1747 if (!isDoubleSpacedVectorIndexed()) return false;
1748 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1749 }
1750
1751 bool isVecListThreeQHWordIndexed() const {
1752 if (!isDoubleSpacedVectorIndexed()) return false;
1753 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1754 }
1755
1756 bool isVecListThreeDWordIndexed() const {
1757 if (!isSingleSpacedVectorIndexed()) return false;
1758 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1759 }
1760
1761 bool isVecListFourDByteIndexed() const {
1762 if (!isSingleSpacedVectorIndexed()) return false;
1763 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1764 }
1765
1766 bool isVecListFourDHWordIndexed() const {
1767 if (!isSingleSpacedVectorIndexed()) return false;
1768 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1769 }
1770
1771 bool isVecListFourQWordIndexed() const {
1772 if (!isDoubleSpacedVectorIndexed()) return false;
1773 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1774 }
1775
1776 bool isVecListFourQHWordIndexed() const {
1777 if (!isDoubleSpacedVectorIndexed()) return false;
1778 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1779 }
1780
1781 bool isVecListFourDWordIndexed() const {
1782 if (!isSingleSpacedVectorIndexed()) return false;
1783 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1784 }
1785
1786 bool isVectorIndex8() const {
1787 if (Kind != k_VectorIndex) return false;
1788 return VectorIndex.Val < 8;
1789 }
1790
1791 bool isVectorIndex16() const {
1792 if (Kind != k_VectorIndex) return false;
1793 return VectorIndex.Val < 4;
1794 }
1795
1796 bool isVectorIndex32() const {
1797 if (Kind != k_VectorIndex) return false;
1798 return VectorIndex.Val < 2;
1799 }
1800 bool isVectorIndex64() const {
1801 if (Kind != k_VectorIndex) return false;
1802 return VectorIndex.Val < 1;
1803 }
1804
1805 bool isNEONi8splat() const {
1806 if (!isImm()) return false;
1807 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1808 // Must be a constant.
1809 if (!CE) return false;
1810 int64_t Value = CE->getValue();
1811 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1812 // value.
1813 return Value >= 0 && Value < 256;
1814 }
1815
1816 bool isNEONi16splat() const {
1817 if (isNEONByteReplicate(2))
1818 return false; // Leave that for bytes replication and forbid by default.
1819 if (!isImm())
1820 return false;
1821 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1822 // Must be a constant.
1823 if (!CE) return false;
1824 unsigned Value = CE->getValue();
1825 return ARM_AM::isNEONi16splat(Value);
1826 }
1827
1828 bool isNEONi16splatNot() const {
1829 if (!isImm())
1830 return false;
1831 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1832 // Must be a constant.
1833 if (!CE) return false;
1834 unsigned Value = CE->getValue();
1835 return ARM_AM::isNEONi16splat(~Value & 0xffff);
1836 }
1837
1838 bool isNEONi32splat() const {
1839 if (isNEONByteReplicate(4))
1840 return false; // Leave that for bytes replication and forbid by default.
1841 if (!isImm())
1842 return false;
1843 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1844 // Must be a constant.
1845 if (!CE) return false;
1846 unsigned Value = CE->getValue();
1847 return ARM_AM::isNEONi32splat(Value);
1848 }
1849
1850 bool isNEONi32splatNot() const {
1851 if (!isImm())
1852 return false;
1853 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1854 // Must be a constant.
1855 if (!CE) return false;
1856 unsigned Value = CE->getValue();
1857 return ARM_AM::isNEONi32splat(~Value);
1858 }
1859
1860 static bool isValidNEONi32vmovImm(int64_t Value) {
1861 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1862 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1863 return ((Value & 0xffffffffffffff00) == 0) ||
1864 ((Value & 0xffffffffffff00ff) == 0) ||
1865 ((Value & 0xffffffffff00ffff) == 0) ||
1866 ((Value & 0xffffffff00ffffff) == 0) ||
1867 ((Value & 0xffffffffffff00ff) == 0xff) ||
1868 ((Value & 0xffffffffff00ffff) == 0xffff);
1869 }
1870
1871 bool isNEONReplicate(unsigned Width, unsigned NumElems, bool Inv) const {
1872 assert((Width == 8 || Width == 16 || Width == 32) &&(static_cast <bool> ((Width == 8 || Width == 16 || Width
== 32) && "Invalid element width") ? void (0) : __assert_fail
("(Width == 8 || Width == 16 || Width == 32) && \"Invalid element width\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1873, __extension__ __PRETTY_FUNCTION__))
1873 "Invalid element width")(static_cast <bool> ((Width == 8 || Width == 16 || Width
== 32) && "Invalid element width") ? void (0) : __assert_fail
("(Width == 8 || Width == 16 || Width == 32) && \"Invalid element width\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1873, __extension__ __PRETTY_FUNCTION__))
;
1874 assert(NumElems * Width <= 64 && "Invalid result width")(static_cast <bool> (NumElems * Width <= 64 &&
"Invalid result width") ? void (0) : __assert_fail ("NumElems * Width <= 64 && \"Invalid result width\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1874, __extension__ __PRETTY_FUNCTION__))
;
1875
1876 if (!isImm())
1877 return false;
1878 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1879 // Must be a constant.
1880 if (!CE)
1881 return false;
1882 int64_t Value = CE->getValue();
1883 if (!Value)
1884 return false; // Don't bother with zero.
1885 if (Inv)
1886 Value = ~Value;
1887
1888 uint64_t Mask = (1ull << Width) - 1;
1889 uint64_t Elem = Value & Mask;
1890 if (Width == 16 && (Elem & 0x00ff) != 0 && (Elem & 0xff00) != 0)
1891 return false;
1892 if (Width == 32 && !isValidNEONi32vmovImm(Elem))
1893 return false;
1894
1895 for (unsigned i = 1; i < NumElems; ++i) {
1896 Value >>= Width;
1897 if ((Value & Mask) != Elem)
1898 return false;
1899 }
1900 return true;
1901 }
1902
1903 bool isNEONByteReplicate(unsigned NumBytes) const {
1904 return isNEONReplicate(8, NumBytes, false);
1905 }
1906
1907 static void checkNeonReplicateArgs(unsigned FromW, unsigned ToW) {
1908 assert((FromW == 8 || FromW == 16 || FromW == 32) &&(static_cast <bool> ((FromW == 8 || FromW == 16 || FromW
== 32) && "Invalid source width") ? void (0) : __assert_fail
("(FromW == 8 || FromW == 16 || FromW == 32) && \"Invalid source width\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1909, __extension__ __PRETTY_FUNCTION__))
1909 "Invalid source width")(static_cast <bool> ((FromW == 8 || FromW == 16 || FromW
== 32) && "Invalid source width") ? void (0) : __assert_fail
("(FromW == 8 || FromW == 16 || FromW == 32) && \"Invalid source width\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1909, __extension__ __PRETTY_FUNCTION__))
;
1910 assert((ToW == 16 || ToW == 32 || ToW == 64) &&(static_cast <bool> ((ToW == 16 || ToW == 32 || ToW == 64
) && "Invalid destination width") ? void (0) : __assert_fail
("(ToW == 16 || ToW == 32 || ToW == 64) && \"Invalid destination width\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1911, __extension__ __PRETTY_FUNCTION__))
1911 "Invalid destination width")(static_cast <bool> ((ToW == 16 || ToW == 32 || ToW == 64
) && "Invalid destination width") ? void (0) : __assert_fail
("(ToW == 16 || ToW == 32 || ToW == 64) && \"Invalid destination width\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1911, __extension__ __PRETTY_FUNCTION__))
;
1912 assert(FromW < ToW && "ToW is not less than FromW")(static_cast <bool> (FromW < ToW && "ToW is not less than FromW"
) ? void (0) : __assert_fail ("FromW < ToW && \"ToW is not less than FromW\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1912, __extension__ __PRETTY_FUNCTION__))
;
1913 }
1914
1915 template<unsigned FromW, unsigned ToW>
1916 bool isNEONmovReplicate() const {
1917 checkNeonReplicateArgs(FromW, ToW);
1918 if (ToW == 64 && isNEONi64splat())
1919 return false;
1920 return isNEONReplicate(FromW, ToW / FromW, false);
1921 }
1922
1923 template<unsigned FromW, unsigned ToW>
1924 bool isNEONinvReplicate() const {
1925 checkNeonReplicateArgs(FromW, ToW);
1926 return isNEONReplicate(FromW, ToW / FromW, true);
1927 }
1928
1929 bool isNEONi32vmov() const {
1930 if (isNEONByteReplicate(4))
1931 return false; // Let it to be classified as byte-replicate case.
1932 if (!isImm())
1933 return false;
1934 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1935 // Must be a constant.
1936 if (!CE)
1937 return false;
1938 return isValidNEONi32vmovImm(CE->getValue());
1939 }
1940
1941 bool isNEONi32vmovNeg() const {
1942 if (!isImm()) return false;
1943 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1944 // Must be a constant.
1945 if (!CE) return false;
1946 return isValidNEONi32vmovImm(~CE->getValue());
1947 }
1948
1949 bool isNEONi64splat() const {
1950 if (!isImm()) return false;
1951 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1952 // Must be a constant.
1953 if (!CE) return false;
1954 uint64_t Value = CE->getValue();
1955 // i64 value with each byte being either 0 or 0xff.
1956 for (unsigned i = 0; i < 8; ++i, Value >>= 8)
1957 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1958 return true;
1959 }
1960
1961 template<int64_t Angle, int64_t Remainder>
1962 bool isComplexRotation() const {
1963 if (!isImm()) return false;
1964
1965 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1966 if (!CE) return false;
1967 uint64_t Value = CE->getValue();
1968
1969 return (Value % Angle == Remainder && Value <= 270);
1970 }
1971
1972 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1973 // Add as immediates when possible. Null MCExpr = 0.
1974 if (!Expr)
1975 Inst.addOperand(MCOperand::createImm(0));
1976 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1977 Inst.addOperand(MCOperand::createImm(CE->getValue()));
1978 else
1979 Inst.addOperand(MCOperand::createExpr(Expr));
1980 }
1981
1982 void addARMBranchTargetOperands(MCInst &Inst, unsigned N) const {
1983 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1983, __extension__ __PRETTY_FUNCTION__))
;
1984 addExpr(Inst, getImm());
1985 }
1986
1987 void addThumbBranchTargetOperands(MCInst &Inst, unsigned N) const {
1988 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1988, __extension__ __PRETTY_FUNCTION__))
;
1989 addExpr(Inst, getImm());
1990 }
1991
1992 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1993 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 1993, __extension__ __PRETTY_FUNCTION__))
;
1994 Inst.addOperand(MCOperand::createImm(unsigned(getCondCode())));
1995 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1996 Inst.addOperand(MCOperand::createReg(RegNum));
1997 }
1998
1999 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
2000 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2000, __extension__ __PRETTY_FUNCTION__))
;
2001 Inst.addOperand(MCOperand::createImm(getCoproc()));
2002 }
2003
2004 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
2005 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2005, __extension__ __PRETTY_FUNCTION__))
;
2006 Inst.addOperand(MCOperand::createImm(getCoproc()));
2007 }
2008
2009 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
2010 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2010, __extension__ __PRETTY_FUNCTION__))
;
2011 Inst.addOperand(MCOperand::createImm(CoprocOption.Val));
2012 }
2013
2014 void addITMaskOperands(MCInst &Inst, unsigned N) const {
2015 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2015, __extension__ __PRETTY_FUNCTION__))
;
2016 Inst.addOperand(MCOperand::createImm(ITMask.Mask));
2017 }
2018
2019 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
2020 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2020, __extension__ __PRETTY_FUNCTION__))
;
2021 Inst.addOperand(MCOperand::createImm(unsigned(getCondCode())));
2022 }
2023
2024 void addCCOutOperands(MCInst &Inst, unsigned N) const {
2025 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2025, __extension__ __PRETTY_FUNCTION__))
;
2026 Inst.addOperand(MCOperand::createReg(getReg()));
2027 }
2028
2029 void addRegOperands(MCInst &Inst, unsigned N) const {
2030 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2030, __extension__ __PRETTY_FUNCTION__))
;
2031 Inst.addOperand(MCOperand::createReg(getReg()));
2032 }
2033
2034 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
2035 assert(N == 3 && "Invalid number of operands!")(static_cast <bool> (N == 3 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 3 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2035, __extension__ __PRETTY_FUNCTION__))
;
2036 assert(isRegShiftedReg() &&(static_cast <bool> (isRegShiftedReg() && "addRegShiftedRegOperands() on non-RegShiftedReg!"
) ? void (0) : __assert_fail ("isRegShiftedReg() && \"addRegShiftedRegOperands() on non-RegShiftedReg!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2037, __extension__ __PRETTY_FUNCTION__))
2037 "addRegShiftedRegOperands() on non-RegShiftedReg!")(static_cast <bool> (isRegShiftedReg() && "addRegShiftedRegOperands() on non-RegShiftedReg!"
) ? void (0) : __assert_fail ("isRegShiftedReg() && \"addRegShiftedRegOperands() on non-RegShiftedReg!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2037, __extension__ __PRETTY_FUNCTION__))
;
2038 Inst.addOperand(MCOperand::createReg(RegShiftedReg.SrcReg));
2039 Inst.addOperand(MCOperand::createReg(RegShiftedReg.ShiftReg));
2040 Inst.addOperand(MCOperand::createImm(
2041 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
2042 }
2043
2044 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
2045 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2045, __extension__ __PRETTY_FUNCTION__))
;
2046 assert(isRegShiftedImm() &&(static_cast <bool> (isRegShiftedImm() && "addRegShiftedImmOperands() on non-RegShiftedImm!"
) ? void (0) : __assert_fail ("isRegShiftedImm() && \"addRegShiftedImmOperands() on non-RegShiftedImm!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2047, __extension__ __PRETTY_FUNCTION__))
2047 "addRegShiftedImmOperands() on non-RegShiftedImm!")(static_cast <bool> (isRegShiftedImm() && "addRegShiftedImmOperands() on non-RegShiftedImm!"
) ? void (0) : __assert_fail ("isRegShiftedImm() && \"addRegShiftedImmOperands() on non-RegShiftedImm!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2047, __extension__ __PRETTY_FUNCTION__))
;
2048 Inst.addOperand(MCOperand::createReg(RegShiftedImm.SrcReg));
2049 // Shift of #32 is encoded as 0 where permitted
2050 unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm);
2051 Inst.addOperand(MCOperand::createImm(
2052 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm)));
2053 }
2054
2055 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
2056 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2056, __extension__ __PRETTY_FUNCTION__))
;
2057 Inst.addOperand(MCOperand::createImm((ShifterImm.isASR << 5) |
2058 ShifterImm.Imm));
2059 }
2060
2061 void addRegListOperands(MCInst &Inst, unsigned N) const {
2062 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2062, __extension__ __PRETTY_FUNCTION__))
;
2063 const SmallVectorImpl<unsigned> &RegList = getRegList();
2064 for (SmallVectorImpl<unsigned>::const_iterator
2065 I = RegList.begin(), E = RegList.end(); I != E; ++I)
2066 Inst.addOperand(MCOperand::createReg(*I));
2067 }
2068
2069 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
2070 addRegListOperands(Inst, N);
2071 }
2072
2073 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
2074 addRegListOperands(Inst, N);
2075 }
2076
2077 void addRotImmOperands(MCInst &Inst, unsigned N) const {
2078 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2078, __extension__ __PRETTY_FUNCTION__))
;
2079 // Encoded as val>>3. The printer handles display as 8, 16, 24.
2080 Inst.addOperand(MCOperand::createImm(RotImm.Imm >> 3));
2081 }
2082
2083 void addModImmOperands(MCInst &Inst, unsigned N) const {
2084 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2084, __extension__ __PRETTY_FUNCTION__))
;
2085
2086 // Support for fixups (MCFixup)
2087 if (isImm())
2088 return addImmOperands(Inst, N);
2089
2090 Inst.addOperand(MCOperand::createImm(ModImm.Bits | (ModImm.Rot << 7)));
2091 }
2092
2093 void addModImmNotOperands(MCInst &Inst, unsigned N) const {
2094 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2094, __extension__ __PRETTY_FUNCTION__))
;
2095 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2096 uint32_t Enc = ARM_AM::getSOImmVal(~CE->getValue());
2097 Inst.addOperand(MCOperand::createImm(Enc));
2098 }
2099
2100 void addModImmNegOperands(MCInst &Inst, unsigned N) const {
2101 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2101, __extension__ __PRETTY_FUNCTION__))
;
2102 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2103 uint32_t Enc = ARM_AM::getSOImmVal(-CE->getValue());
2104 Inst.addOperand(MCOperand::createImm(Enc));
2105 }
2106
2107 void addThumbModImmNeg8_255Operands(MCInst &Inst, unsigned N) const {
2108 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2108, __extension__ __PRETTY_FUNCTION__))
;
2109 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2110 uint32_t Val = -CE->getValue();
2111 Inst.addOperand(MCOperand::createImm(Val));
2112 }
2113
2114 void addThumbModImmNeg1_7Operands(MCInst &Inst, unsigned N) const {
2115 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2115, __extension__ __PRETTY_FUNCTION__))
;
2116 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2117 uint32_t Val = -CE->getValue();
2118 Inst.addOperand(MCOperand::createImm(Val));
2119 }
2120
2121 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
2122 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2122, __extension__ __PRETTY_FUNCTION__))
;
2123 // Munge the lsb/width into a bitfield mask.
2124 unsigned lsb = Bitfield.LSB;
2125 unsigned width = Bitfield.Width;
2126 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
2127 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
2128 (32 - (lsb + width)));
2129 Inst.addOperand(MCOperand::createImm(Mask));
2130 }
2131
2132 void addImmOperands(MCInst &Inst, unsigned N) const {
2133 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2133, __extension__ __PRETTY_FUNCTION__))
;
2134 addExpr(Inst, getImm());
2135 }
2136
2137 void addFBits16Operands(MCInst &Inst, unsigned N) const {
2138 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2138, __extension__ __PRETTY_FUNCTION__))
;
2139 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2140 Inst.addOperand(MCOperand::createImm(16 - CE->getValue()));
2141 }
2142
2143 void addFBits32Operands(MCInst &Inst, unsigned N) const {
2144 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2144, __extension__ __PRETTY_FUNCTION__))
;
2145 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2146 Inst.addOperand(MCOperand::createImm(32 - CE->getValue()));
2147 }
2148
2149 void addFPImmOperands(MCInst &Inst, unsigned N) const {
2150 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2150, __extension__ __PRETTY_FUNCTION__))
;
2151 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2152 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
2153 Inst.addOperand(MCOperand::createImm(Val));
2154 }
2155
2156 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
2157 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2157, __extension__ __PRETTY_FUNCTION__))
;
2158 // FIXME: We really want to scale the value here, but the LDRD/STRD
2159 // instruction don't encode operands that way yet.
2160 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2161 Inst.addOperand(MCOperand::createImm(CE->getValue()));
2162 }
2163
2164 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
2165 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2165, __extension__ __PRETTY_FUNCTION__))
;
2166 // The immediate is scaled by four in the encoding and is stored
2167 // in the MCInst as such. Lop off the low two bits here.
2168 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2169 Inst.addOperand(MCOperand::createImm(CE->getValue() / 4));
2170 }
2171
2172 void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
2173 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2173, __extension__ __PRETTY_FUNCTION__))
;
2174 // The immediate is scaled by four in the encoding and is stored
2175 // in the MCInst as such. Lop off the low two bits here.
2176 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2177 Inst.addOperand(MCOperand::createImm(-(CE->getValue() / 4)));
2178 }
2179
2180 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
2181 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2181, __extension__ __PRETTY_FUNCTION__))
;
2182 // The immediate is scaled by four in the encoding and is stored
2183 // in the MCInst as such. Lop off the low two bits here.
2184 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2185 Inst.addOperand(MCOperand::createImm(CE->getValue() / 4));
2186 }
2187
2188 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
2189 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2189, __extension__ __PRETTY_FUNCTION__))
;
2190 // The constant encodes as the immediate-1, and we store in the instruction
2191 // the bits as encoded, so subtract off one here.
2192 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2193 Inst.addOperand(MCOperand::createImm(CE->getValue() - 1));
2194 }
2195
2196 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
2197 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2197, __extension__ __PRETTY_FUNCTION__))
;
2198 // The constant encodes as the immediate-1, and we store in the instruction
2199 // the bits as encoded, so subtract off one here.
2200 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2201 Inst.addOperand(MCOperand::createImm(CE->getValue() - 1));
2202 }
2203
2204 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
2205 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2205, __extension__ __PRETTY_FUNCTION__))
;
2206 // The constant encodes as the immediate, except for 32, which encodes as
2207 // zero.
2208 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2209 unsigned Imm = CE->getValue();
2210 Inst.addOperand(MCOperand::createImm((Imm == 32 ? 0 : Imm)));
2211 }
2212
2213 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
2214 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2214, __extension__ __PRETTY_FUNCTION__))
;
2215 // An ASR value of 32 encodes as 0, so that's how we want to add it to
2216 // the instruction as well.
2217 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2218 int Val = CE->getValue();
2219 Inst.addOperand(MCOperand::createImm(Val == 32 ? 0 : Val));
2220 }
2221
2222 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
2223 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2223, __extension__ __PRETTY_FUNCTION__))
;
2224 // The operand is actually a t2_so_imm, but we have its bitwise
2225 // negation in the assembly source, so twiddle it here.
2226 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2227 Inst.addOperand(MCOperand::createImm(~(uint32_t)CE->getValue()));
2228 }
2229
2230 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
2231 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2231, __extension__ __PRETTY_FUNCTION__))
;
2232 // The operand is actually a t2_so_imm, but we have its
2233 // negation in the assembly source, so twiddle it here.
2234 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2235 Inst.addOperand(MCOperand::createImm(-(uint32_t)CE->getValue()));
2236 }
2237
2238 void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
2239 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2239, __extension__ __PRETTY_FUNCTION__))
;
2240 // The operand is actually an imm0_4095, but we have its
2241 // negation in the assembly source, so twiddle it here.
2242 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2243 Inst.addOperand(MCOperand::createImm(-CE->getValue()));
2244 }
2245
2246 void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const {
2247 if(const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) {
2248 Inst.addOperand(MCOperand::createImm(CE->getValue() >> 2));
2249 return;
2250 }
2251
2252 const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
2253 assert(SR && "Unknown value type!")(static_cast <bool> (SR && "Unknown value type!"
) ? void (0) : __assert_fail ("SR && \"Unknown value type!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2253, __extension__ __PRETTY_FUNCTION__))
;
2254 Inst.addOperand(MCOperand::createExpr(SR));
2255 }
2256
2257 void addThumbMemPCOperands(MCInst &Inst, unsigned N) const {
2258 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2258, __extension__ __PRETTY_FUNCTION__))
;
2259 if (isImm()) {
2260 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2261 if (CE) {
2262 Inst.addOperand(MCOperand::createImm(CE->getValue()));
2263 return;
2264 }
2265
2266 const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
2267
2268 assert(SR && "Unknown value type!")(static_cast <bool> (SR && "Unknown value type!"
) ? void (0) : __assert_fail ("SR && \"Unknown value type!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2268, __extension__ __PRETTY_FUNCTION__))
;
2269 Inst.addOperand(MCOperand::createExpr(SR));
2270 return;
2271 }
2272
2273 assert(isMem() && "Unknown value type!")(static_cast <bool> (isMem() && "Unknown value type!"
) ? void (0) : __assert_fail ("isMem() && \"Unknown value type!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2273, __extension__ __PRETTY_FUNCTION__))
;
2274 assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!")(static_cast <bool> (isa<MCConstantExpr>(Memory.OffsetImm
) && "Unknown value type!") ? void (0) : __assert_fail
("isa<MCConstantExpr>(Memory.OffsetImm) && \"Unknown value type!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2274, __extension__ __PRETTY_FUNCTION__))
;
2275 Inst.addOperand(MCOperand::createImm(Memory.OffsetImm->getValue()));
2276 }
2277
2278 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
2279 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2279, __extension__ __PRETTY_FUNCTION__))
;
2280 Inst.addOperand(MCOperand::createImm(unsigned(getMemBarrierOpt())));
2281 }
2282
2283 void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const {
2284 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2284, __extension__ __PRETTY_FUNCTION__))
;
2285 Inst.addOperand(MCOperand::createImm(unsigned(getInstSyncBarrierOpt())));
2286 }
2287
2288 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
2289 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2289, __extension__ __PRETTY_FUNCTION__))
;
2290 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2291 }
2292
2293 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
2294 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2294, __extension__ __PRETTY_FUNCTION__))
;
2295 int32_t Imm = Memory.OffsetImm->getValue();
2296 Inst.addOperand(MCOperand::createImm(Imm));
2297 }
2298
2299 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
2300 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2300, __extension__ __PRETTY_FUNCTION__))
;
2301 assert(isImm() && "Not an immediate!")(static_cast <bool> (isImm() && "Not an immediate!"
) ? void (0) : __assert_fail ("isImm() && \"Not an immediate!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2301, __extension__ __PRETTY_FUNCTION__))
;
2302
2303 // If we have an immediate that's not a constant, treat it as a label
2304 // reference needing a fixup.
2305 if (!isa<MCConstantExpr>(getImm())) {
2306 Inst.addOperand(MCOperand::createExpr(getImm()));
2307 return;
2308 }
2309
2310 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2311 int Val = CE->getValue();
2312 Inst.addOperand(MCOperand::createImm(Val));
2313 }
2314
2315 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
2316 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2316, __extension__ __PRETTY_FUNCTION__))
;
2317 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2318 Inst.addOperand(MCOperand::createImm(Memory.Alignment));
2319 }
2320
2321 void addDupAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const {
2322 addAlignedMemoryOperands(Inst, N);
2323 }
2324
2325 void addAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const {
2326 addAlignedMemoryOperands(Inst, N);
2327 }
2328
2329 void addAlignedMemory16Operands(MCInst &Inst, unsigned N) const {
2330 addAlignedMemoryOperands(Inst, N);
2331 }
2332
2333 void addDupAlignedMemory16Operands(MCInst &Inst, unsigned N) const {
2334 addAlignedMemoryOperands(Inst, N);
2335 }
2336
2337 void addAlignedMemory32Operands(MCInst &Inst, unsigned N) const {
2338 addAlignedMemoryOperands(Inst, N);
2339 }
2340
2341 void addDupAlignedMemory32Operands(MCInst &Inst, unsigned N) const {
2342 addAlignedMemoryOperands(Inst, N);
2343 }
2344
2345 void addAlignedMemory64Operands(MCInst &Inst, unsigned N) const {
2346 addAlignedMemoryOperands(Inst, N);
2347 }
2348
2349 void addDupAlignedMemory64Operands(MCInst &Inst, unsigned N) const {
2350 addAlignedMemoryOperands(Inst, N);
2351 }
2352
2353 void addAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const {
2354 addAlignedMemoryOperands(Inst, N);
2355 }
2356
2357 void addDupAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const {
2358 addAlignedMemoryOperands(Inst, N);
2359 }
2360
2361 void addAlignedMemory64or128or256Operands(MCInst &Inst, unsigned N) const {
2362 addAlignedMemoryOperands(Inst, N);
2363 }
2364
2365 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
2366 assert(N == 3 && "Invalid number of operands!")(static_cast <bool> (N == 3 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 3 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2366, __extension__ __PRETTY_FUNCTION__))
;
2367 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2368 if (!Memory.OffsetRegNum) {
2369 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2370 // Special case for #-0
2371 if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
2372 if (Val < 0) Val = -Val;
2373 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
2374 } else {
2375 // For register offset, we encode the shift type and negation flag
2376 // here.
2377 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
2378 Memory.ShiftImm, Memory.ShiftType);
2379 }
2380 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2381 Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2382 Inst.addOperand(MCOperand::createImm(Val));
2383 }
2384
2385 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
2386 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2386, __extension__ __PRETTY_FUNCTION__))
;
2387 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2388 assert(CE && "non-constant AM2OffsetImm operand!")(static_cast <bool> (CE && "non-constant AM2OffsetImm operand!"
) ? void (0) : __assert_fail ("CE && \"non-constant AM2OffsetImm operand!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2388, __extension__ __PRETTY_FUNCTION__))
;
2389 int32_t Val = CE->getValue();
2390 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2391 // Special case for #-0
2392 if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
2393 if (Val < 0) Val = -Val;
2394 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
2395 Inst.addOperand(MCOperand::createReg(0));
2396 Inst.addOperand(MCOperand::createImm(Val));
2397 }
2398
2399 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
2400 assert(N == 3 && "Invalid number of operands!")(static_cast <bool> (N == 3 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 3 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2400, __extension__ __PRETTY_FUNCTION__))
;
2401 // If we have an immediate that's not a constant, treat it as a label
2402 // reference needing a fixup. If it is a constant, it's something else
2403 // and we reject it.
2404 if (isImm()) {
2405 Inst.addOperand(MCOperand::createExpr(getImm()));
2406 Inst.addOperand(MCOperand::createReg(0));
2407 Inst.addOperand(MCOperand::createImm(0));
2408 return;
2409 }
2410
2411 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2412 if (!Memory.OffsetRegNum) {
2413 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2414 // Special case for #-0
2415 if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
2416 if (Val < 0) Val = -Val;
2417 Val = ARM_AM::getAM3Opc(AddSub, Val);
2418 } else {
2419 // For register offset, we encode the shift type and negation flag
2420 // here.
2421 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
2422 }
2423 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2424 Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2425 Inst.addOperand(MCOperand::createImm(Val));
2426 }
2427
2428 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
2429 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2429, __extension__ __PRETTY_FUNCTION__))
;
2430 if (Kind == k_PostIndexRegister) {
2431 int32_t Val =
2432 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
2433 Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum));
2434 Inst.addOperand(MCOperand::createImm(Val));
2435 return;
2436 }
2437
2438 // Constant offset.
2439 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
2440 int32_t Val = CE->getValue();
2441 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2442 // Special case for #-0
2443 if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
2444 if (Val < 0) Val = -Val;
2445 Val = ARM_AM::getAM3Opc(AddSub, Val);
2446 Inst.addOperand(MCOperand::createReg(0));
2447 Inst.addOperand(MCOperand::createImm(Val));
2448 }
2449
2450 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
2451 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2451, __extension__ __PRETTY_FUNCTION__))
;
2452 // If we have an immediate that's not a constant, treat it as a label
2453 // reference needing a fixup. If it is a constant, it's something else
2454 // and we reject it.
2455 if (isImm()) {
2456 Inst.addOperand(MCOperand::createExpr(getImm()));
2457 Inst.addOperand(MCOperand::createImm(0));
2458 return;
2459 }
2460
2461 // The lower two bits are always zero and as such are not encoded.
2462 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
2463 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2464 // Special case for #-0
2465 if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
2466 if (Val < 0) Val = -Val;
2467 Val = ARM_AM::getAM5Opc(AddSub, Val);
2468 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2469 Inst.addOperand(MCOperand::createImm(Val));
2470 }
2471
2472 void addAddrMode5FP16Operands(MCInst &Inst, unsigned N) const {
2473 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2473, __extension__ __PRETTY_FUNCTION__))
;
2474 // If we have an immediate that's not a constant, treat it as a label
2475 // reference needing a fixup. If it is a constant, it's something else
2476 // and we reject it.
2477 if (isImm()) {
2478 Inst.addOperand(MCOperand::createExpr(getImm()));
2479 Inst.addOperand(MCOperand::createImm(0));
2480 return;
2481 }
2482
2483 // The lower bit is always zero and as such is not encoded.
2484 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 2 : 0;
2485 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2486 // Special case for #-0
2487 if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
2488 if (Val < 0) Val = -Val;
2489 Val = ARM_AM::getAM5FP16Opc(AddSub, Val);
2490 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2491 Inst.addOperand(MCOperand::createImm(Val));
2492 }
2493
2494 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
2495 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2495, __extension__ __PRETTY_FUNCTION__))
;
2496 // If we have an immediate that's not a constant, treat it as a label
2497 // reference needing a fixup. If it is a constant, it's something else
2498 // and we reject it.
2499 if (isImm()) {
2500 Inst.addOperand(MCOperand::createExpr(getImm()));
2501 Inst.addOperand(MCOperand::createImm(0));
2502 return;
2503 }
2504
2505 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2506 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2507 Inst.addOperand(MCOperand::createImm(Val));
2508 }
2509
2510 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
2511 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2511, __extension__ __PRETTY_FUNCTION__))
;
2512 // The lower two bits are always zero and as such are not encoded.
2513 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
2514 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2515 Inst.addOperand(MCOperand::createImm(Val));
2516 }
2517
2518 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
2519 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2519, __extension__ __PRETTY_FUNCTION__))
;
2520 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2521 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2522 Inst.addOperand(MCOperand::createImm(Val));
2523 }
2524
2525 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
2526 addMemImm8OffsetOperands(Inst, N);
2527 }
2528
2529 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
2530 addMemImm8OffsetOperands(Inst, N);
2531 }
2532
2533 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
2534 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2534, __extension__ __PRETTY_FUNCTION__))
;
2535 // If this is an immediate, it's a label reference.
2536 if (isImm()) {
2537 addExpr(Inst, getImm());
2538 Inst.addOperand(MCOperand::createImm(0));
2539 return;
2540 }
2541
2542 // Otherwise, it's a normal memory reg+offset.
2543 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2544 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2545 Inst.addOperand(MCOperand::createImm(Val));
2546 }
2547
2548 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
2549 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2549, __extension__ __PRETTY_FUNCTION__))
;
2550 // If this is an immediate, it's a label reference.
2551 if (isImm()) {
2552 addExpr(Inst, getImm());
2553 Inst.addOperand(MCOperand::createImm(0));
2554 return;
2555 }
2556
2557 // Otherwise, it's a normal memory reg+offset.
2558 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2559 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2560 Inst.addOperand(MCOperand::createImm(Val));
2561 }
2562
2563 void addConstPoolAsmImmOperands(MCInst &Inst, unsigned N) const {
2564 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2564, __extension__ __PRETTY_FUNCTION__))
;
2565 // This is container for the immediate that we will create the constant
2566 // pool from
2567 addExpr(Inst, getConstantPoolImm());
2568 return;
2569 }
2570
2571 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
2572 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2572, __extension__ __PRETTY_FUNCTION__))
;
2573 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2574 Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2575 }
2576
2577 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
2578 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2578, __extension__ __PRETTY_FUNCTION__))
;
2579 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2580 Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2581 }
2582
2583 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
2584 assert(N == 3 && "Invalid number of operands!")(static_cast <bool> (N == 3 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 3 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2584, __extension__ __PRETTY_FUNCTION__))
;
2585 unsigned Val =
2586 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
2587 Memory.ShiftImm, Memory.ShiftType);
2588 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2589 Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2590 Inst.addOperand(MCOperand::createImm(Val));
2591 }
2592
2593 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
2594 assert(N == 3 && "Invalid number of operands!")(static_cast <bool> (N == 3 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 3 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2594, __extension__ __PRETTY_FUNCTION__))
;
2595 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2596 Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2597 Inst.addOperand(MCOperand::createImm(Memory.ShiftImm));
2598 }
2599
2600 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
2601 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2601, __extension__ __PRETTY_FUNCTION__))
;
2602 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2603 Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
2604 }
2605
2606 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
2607 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2607, __extension__ __PRETTY_FUNCTION__))
;
2608 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
2609 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2610 Inst.addOperand(MCOperand::createImm(Val));
2611 }
2612
2613 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
2614 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2614, __extension__ __PRETTY_FUNCTION__))
;
2615 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
2616 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2617 Inst.addOperand(MCOperand::createImm(Val));
2618 }
2619
2620 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
2621 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2621, __extension__ __PRETTY_FUNCTION__))
;
2622 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
2623 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2624 Inst.addOperand(MCOperand::createImm(Val));
2625 }
2626
2627 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
2628 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2628, __extension__ __PRETTY_FUNCTION__))
;
2629 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
2630 Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
2631 Inst.addOperand(MCOperand::createImm(Val));
2632 }
2633
2634 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
2635 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2635, __extension__ __PRETTY_FUNCTION__))
;
2636 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2637 assert(CE && "non-constant post-idx-imm8 operand!")(static_cast <bool> (CE && "non-constant post-idx-imm8 operand!"
) ? void (0) : __assert_fail ("CE && \"non-constant post-idx-imm8 operand!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2637, __extension__ __PRETTY_FUNCTION__))
;
2638 int Imm = CE->getValue();
2639 bool isAdd = Imm >= 0;
2640 if (Imm == std::numeric_limits<int32_t>::min()) Imm = 0;
2641 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
2642 Inst.addOperand(MCOperand::createImm(Imm));
2643 }
2644
2645 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
2646 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2646, __extension__ __PRETTY_FUNCTION__))
;
2647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2648 assert(CE && "non-constant post-idx-imm8s4 operand!")(static_cast <bool> (CE && "non-constant post-idx-imm8s4 operand!"
) ? void (0) : __assert_fail ("CE && \"non-constant post-idx-imm8s4 operand!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2648, __extension__ __PRETTY_FUNCTION__))
;
2649 int Imm = CE->getValue();
2650 bool isAdd = Imm >= 0;
2651 if (Imm == std::numeric_limits<int32_t>::min()) Imm = 0;
2652 // Immediate is scaled by 4.
2653 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
2654 Inst.addOperand(MCOperand::createImm(Imm));
2655 }
2656
2657 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
2658 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2658, __extension__ __PRETTY_FUNCTION__))
;
2659 Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum));
2660 Inst.addOperand(MCOperand::createImm(PostIdxReg.isAdd));
2661 }
2662
2663 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
2664 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2664, __extension__ __PRETTY_FUNCTION__))
;
2665 Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum));
2666 // The sign, shift type, and shift amount are encoded in a single operand
2667 // using the AM2 encoding helpers.
2668 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
2669 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
2670 PostIdxReg.ShiftTy);
2671 Inst.addOperand(MCOperand::createImm(Imm));
2672 }
2673
2674 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
2675 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2675, __extension__ __PRETTY_FUNCTION__))
;
2676 Inst.addOperand(MCOperand::createImm(unsigned(getMSRMask())));
2677 }
2678
2679 void addBankedRegOperands(MCInst &Inst, unsigned N) const {
2680 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2680, __extension__ __PRETTY_FUNCTION__))
;
2681 Inst.addOperand(MCOperand::createImm(unsigned(getBankedReg())));
2682 }
2683
2684 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
2685 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2685, __extension__ __PRETTY_FUNCTION__))
;
2686 Inst.addOperand(MCOperand::createImm(unsigned(getProcIFlags())));
2687 }
2688
2689 void addVecListOperands(MCInst &Inst, unsigned N) const {
2690 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2690, __extension__ __PRETTY_FUNCTION__))
;
2691 Inst.addOperand(MCOperand::createReg(VectorList.RegNum));
2692 }
2693
2694 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
2695 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2695, __extension__ __PRETTY_FUNCTION__))
;
2696 Inst.addOperand(MCOperand::createReg(VectorList.RegNum));
2697 Inst.addOperand(MCOperand::createImm(VectorList.LaneIndex));
2698 }
2699
2700 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
2701 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2701, __extension__ __PRETTY_FUNCTION__))
;
2702 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
2703 }
2704
2705 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
2706 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2706, __extension__ __PRETTY_FUNCTION__))
;
2707 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
2708 }
2709
2710 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
2711 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2711, __extension__ __PRETTY_FUNCTION__))
;
2712 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
2713 }
2714
2715 void addVectorIndex64Operands(MCInst &Inst, unsigned N) const {
2716 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2716, __extension__ __PRETTY_FUNCTION__))
;
2717 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
2718 }
2719
2720 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
2721 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2721, __extension__ __PRETTY_FUNCTION__))
;
2722 // The immediate encodes the type of constant as well as the value.
2723 // Mask in that this is an i8 splat.
2724 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2725 Inst.addOperand(MCOperand::createImm(CE->getValue() | 0xe00));
2726 }
2727
2728 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
2729 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2729, __extension__ __PRETTY_FUNCTION__))
;
2730 // The immediate encodes the type of constant as well as the value.
2731 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2732 unsigned Value = CE->getValue();
2733 Value = ARM_AM::encodeNEONi16splat(Value);
2734 Inst.addOperand(MCOperand::createImm(Value));
2735 }
2736
2737 void addNEONi16splatNotOperands(MCInst &Inst, unsigned N) const {
2738 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2738, __extension__ __PRETTY_FUNCTION__))
;
2739 // The immediate encodes the type of constant as well as the value.
2740 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2741 unsigned Value = CE->getValue();
2742 Value = ARM_AM::encodeNEONi16splat(~Value & 0xffff);
2743 Inst.addOperand(MCOperand::createImm(Value));
2744 }
2745
2746 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
2747 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2747, __extension__ __PRETTY_FUNCTION__))
;
2748 // The immediate encodes the type of constant as well as the value.
2749 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2750 unsigned Value = CE->getValue();
2751 Value = ARM_AM::encodeNEONi32splat(Value);
2752 Inst.addOperand(MCOperand::createImm(Value));
2753 }
2754
2755 void addNEONi32splatNotOperands(MCInst &Inst, unsigned N) const {
2756 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2756, __extension__ __PRETTY_FUNCTION__))
;
2757 // The immediate encodes the type of constant as well as the value.
2758 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2759 unsigned Value = CE->getValue();
2760 Value = ARM_AM::encodeNEONi32splat(~Value);
2761 Inst.addOperand(MCOperand::createImm(Value));
2762 }
2763
2764 void addNEONi8ReplicateOperands(MCInst &Inst, bool Inv) const {
2765 // The immediate encodes the type of constant as well as the value.
2766 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2767 assert((Inst.getOpcode() == ARM::VMOVv8i8 ||(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv8i8
|| Inst.getOpcode() == ARM::VMOVv16i8) && "All instructions that wants to replicate non-zero byte "
"always must be replaced with VMOVv8i8 or VMOVv16i8.") ? void
(0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv8i8 || Inst.getOpcode() == ARM::VMOVv16i8) && \"All instructions that wants to replicate non-zero byte \" \"always must be replaced with VMOVv8i8 or VMOVv16i8.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2770, __extension__ __PRETTY_FUNCTION__))
2768 Inst.getOpcode() == ARM::VMOVv16i8) &&(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv8i8
|| Inst.getOpcode() == ARM::VMOVv16i8) && "All instructions that wants to replicate non-zero byte "
"always must be replaced with VMOVv8i8 or VMOVv16i8.") ? void
(0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv8i8 || Inst.getOpcode() == ARM::VMOVv16i8) && \"All instructions that wants to replicate non-zero byte \" \"always must be replaced with VMOVv8i8 or VMOVv16i8.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2770, __extension__ __PRETTY_FUNCTION__))
2769 "All instructions that wants to replicate non-zero byte "(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv8i8
|| Inst.getOpcode() == ARM::VMOVv16i8) && "All instructions that wants to replicate non-zero byte "
"always must be replaced with VMOVv8i8 or VMOVv16i8.") ? void
(0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv8i8 || Inst.getOpcode() == ARM::VMOVv16i8) && \"All instructions that wants to replicate non-zero byte \" \"always must be replaced with VMOVv8i8 or VMOVv16i8.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2770, __extension__ __PRETTY_FUNCTION__))
2770 "always must be replaced with VMOVv8i8 or VMOVv16i8.")(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv8i8
|| Inst.getOpcode() == ARM::VMOVv16i8) && "All instructions that wants to replicate non-zero byte "
"always must be replaced with VMOVv8i8 or VMOVv16i8.") ? void
(0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv8i8 || Inst.getOpcode() == ARM::VMOVv16i8) && \"All instructions that wants to replicate non-zero byte \" \"always must be replaced with VMOVv8i8 or VMOVv16i8.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2770, __extension__ __PRETTY_FUNCTION__))
;
2771 unsigned Value = CE->getValue();
2772 if (Inv)
2773 Value = ~Value;
2774 unsigned B = Value & 0xff;
2775 B |= 0xe00; // cmode = 0b1110
2776 Inst.addOperand(MCOperand::createImm(B));
2777 }
2778
2779 void addNEONinvi8ReplicateOperands(MCInst &Inst, unsigned N) const {
2780 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2780, __extension__ __PRETTY_FUNCTION__))
;
2781 addNEONi8ReplicateOperands(Inst, true);
2782 }
2783
2784 static unsigned encodeNeonVMOVImmediate(unsigned Value) {
2785 if (Value >= 256 && Value <= 0xffff)
2786 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2787 else if (Value > 0xffff && Value <= 0xffffff)
2788 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2789 else if (Value > 0xffffff)
2790 Value = (Value >> 24) | 0x600;
2791 return Value;
2792 }
2793
2794 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
2795 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2795, __extension__ __PRETTY_FUNCTION__))
;
2796 // The immediate encodes the type of constant as well as the value.
2797 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2798 unsigned Value = encodeNeonVMOVImmediate(CE->getValue());
2799 Inst.addOperand(MCOperand::createImm(Value));
2800 }
2801
2802 void addNEONvmovi8ReplicateOperands(MCInst &Inst, unsigned N) const {
2803 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2803, __extension__ __PRETTY_FUNCTION__))
;
2804 addNEONi8ReplicateOperands(Inst, false);
2805 }
2806
2807 void addNEONvmovi16ReplicateOperands(MCInst &Inst, unsigned N) const {
2808 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2808, __extension__ __PRETTY_FUNCTION__))
;
2809 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2810 assert((Inst.getOpcode() == ARM::VMOVv4i16 ||(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv4i16
|| Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() ==
ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) &&
"All instructions that want to replicate non-zero half-word "
"always must be replaced with V{MOV,MVN}v{4,8}i16.") ? void (
0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv4i16 || Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() == ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) && \"All instructions that want to replicate non-zero half-word \" \"always must be replaced with V{MOV,MVN}v{4,8}i16.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2815, __extension__ __PRETTY_FUNCTION__))
2811 Inst.getOpcode() == ARM::VMOVv8i16 ||(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv4i16
|| Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() ==
ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) &&
"All instructions that want to replicate non-zero half-word "
"always must be replaced with V{MOV,MVN}v{4,8}i16.") ? void (
0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv4i16 || Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() == ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) && \"All instructions that want to replicate non-zero half-word \" \"always must be replaced with V{MOV,MVN}v{4,8}i16.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2815, __extension__ __PRETTY_FUNCTION__))
2812 Inst.getOpcode() == ARM::VMVNv4i16 ||(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv4i16
|| Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() ==
ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) &&
"All instructions that want to replicate non-zero half-word "
"always must be replaced with V{MOV,MVN}v{4,8}i16.") ? void (
0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv4i16 || Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() == ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) && \"All instructions that want to replicate non-zero half-word \" \"always must be replaced with V{MOV,MVN}v{4,8}i16.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2815, __extension__ __PRETTY_FUNCTION__))
2813 Inst.getOpcode() == ARM::VMVNv8i16) &&(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv4i16
|| Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() ==
ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) &&
"All instructions that want to replicate non-zero half-word "
"always must be replaced with V{MOV,MVN}v{4,8}i16.") ? void (
0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv4i16 || Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() == ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) && \"All instructions that want to replicate non-zero half-word \" \"always must be replaced with V{MOV,MVN}v{4,8}i16.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2815, __extension__ __PRETTY_FUNCTION__))
2814 "All instructions that want to replicate non-zero half-word "(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv4i16
|| Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() ==
ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) &&
"All instructions that want to replicate non-zero half-word "
"always must be replaced with V{MOV,MVN}v{4,8}i16.") ? void (
0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv4i16 || Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() == ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) && \"All instructions that want to replicate non-zero half-word \" \"always must be replaced with V{MOV,MVN}v{4,8}i16.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2815, __extension__ __PRETTY_FUNCTION__))
2815 "always must be replaced with V{MOV,MVN}v{4,8}i16.")(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv4i16
|| Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() ==
ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) &&
"All instructions that want to replicate non-zero half-word "
"always must be replaced with V{MOV,MVN}v{4,8}i16.") ? void (
0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv4i16 || Inst.getOpcode() == ARM::VMOVv8i16 || Inst.getOpcode() == ARM::VMVNv4i16 || Inst.getOpcode() == ARM::VMVNv8i16) && \"All instructions that want to replicate non-zero half-word \" \"always must be replaced with V{MOV,MVN}v{4,8}i16.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2815, __extension__ __PRETTY_FUNCTION__))
;
2816 uint64_t Value = CE->getValue();
2817 unsigned Elem = Value & 0xffff;
2818 if (Elem >= 256)
2819 Elem = (Elem >> 8) | 0x200;
2820 Inst.addOperand(MCOperand::createImm(Elem));
2821 }
2822
2823 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2824 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2824, __extension__ __PRETTY_FUNCTION__))
;
2825 // The immediate encodes the type of constant as well as the value.
2826 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2827 unsigned Value = encodeNeonVMOVImmediate(~CE->getValue());
2828 Inst.addOperand(MCOperand::createImm(Value));
2829 }
2830
2831 void addNEONvmovi32ReplicateOperands(MCInst &Inst, unsigned N) const {
2832 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2832, __extension__ __PRETTY_FUNCTION__))
;
2833 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2834 assert((Inst.getOpcode() == ARM::VMOVv2i32 ||(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv2i32
|| Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() ==
ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) &&
"All instructions that want to replicate non-zero word " "always must be replaced with V{MOV,MVN}v{2,4}i32."
) ? void (0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv2i32 || Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() == ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) && \"All instructions that want to replicate non-zero word \" \"always must be replaced with V{MOV,MVN}v{2,4}i32.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2839, __extension__ __PRETTY_FUNCTION__))
2835 Inst.getOpcode() == ARM::VMOVv4i32 ||(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv2i32
|| Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() ==
ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) &&
"All instructions that want to replicate non-zero word " "always must be replaced with V{MOV,MVN}v{2,4}i32."
) ? void (0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv2i32 || Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() == ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) && \"All instructions that want to replicate non-zero word \" \"always must be replaced with V{MOV,MVN}v{2,4}i32.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2839, __extension__ __PRETTY_FUNCTION__))
2836 Inst.getOpcode() == ARM::VMVNv2i32 ||(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv2i32
|| Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() ==
ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) &&
"All instructions that want to replicate non-zero word " "always must be replaced with V{MOV,MVN}v{2,4}i32."
) ? void (0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv2i32 || Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() == ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) && \"All instructions that want to replicate non-zero word \" \"always must be replaced with V{MOV,MVN}v{2,4}i32.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2839, __extension__ __PRETTY_FUNCTION__))
2837 Inst.getOpcode() == ARM::VMVNv4i32) &&(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv2i32
|| Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() ==
ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) &&
"All instructions that want to replicate non-zero word " "always must be replaced with V{MOV,MVN}v{2,4}i32."
) ? void (0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv2i32 || Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() == ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) && \"All instructions that want to replicate non-zero word \" \"always must be replaced with V{MOV,MVN}v{2,4}i32.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2839, __extension__ __PRETTY_FUNCTION__))
2838 "All instructions that want to replicate non-zero word "(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv2i32
|| Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() ==
ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) &&
"All instructions that want to replicate non-zero word " "always must be replaced with V{MOV,MVN}v{2,4}i32."
) ? void (0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv2i32 || Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() == ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) && \"All instructions that want to replicate non-zero word \" \"always must be replaced with V{MOV,MVN}v{2,4}i32.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2839, __extension__ __PRETTY_FUNCTION__))
2839 "always must be replaced with V{MOV,MVN}v{2,4}i32.")(static_cast <bool> ((Inst.getOpcode() == ARM::VMOVv2i32
|| Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() ==
ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) &&
"All instructions that want to replicate non-zero word " "always must be replaced with V{MOV,MVN}v{2,4}i32."
) ? void (0) : __assert_fail ("(Inst.getOpcode() == ARM::VMOVv2i32 || Inst.getOpcode() == ARM::VMOVv4i32 || Inst.getOpcode() == ARM::VMVNv2i32 || Inst.getOpcode() == ARM::VMVNv4i32) && \"All instructions that want to replicate non-zero word \" \"always must be replaced with V{MOV,MVN}v{2,4}i32.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2839, __extension__ __PRETTY_FUNCTION__))
;
2840 uint64_t Value = CE->getValue();
2841 unsigned Elem = encodeNeonVMOVImmediate(Value & 0xffffffff);
2842 Inst.addOperand(MCOperand::createImm(Elem));
2843 }
2844
2845 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2846 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2846, __extension__ __PRETTY_FUNCTION__))
;
2847 // The immediate encodes the type of constant as well as the value.
2848 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2849 uint64_t Value = CE->getValue();
2850 unsigned Imm = 0;
2851 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2852 Imm |= (Value & 1) << i;
2853 }
2854 Inst.addOperand(MCOperand::createImm(Imm | 0x1e00));
2855 }
2856
2857 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
2858 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2858, __extension__ __PRETTY_FUNCTION__))
;
2859 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2860 Inst.addOperand(MCOperand::createImm(CE->getValue() / 90));
2861 }
2862
2863 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
2864 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 2864, __extension__ __PRETTY_FUNCTION__))
;
2865 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2866 Inst.addOperand(MCOperand::createImm((CE->getValue() - 90) / 180));
2867 }
2868
2869 void print(raw_ostream &OS) const override;
2870
2871 static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S) {
2872 auto Op = make_unique<ARMOperand>(k_ITCondMask);
2873 Op->ITMask.Mask = Mask;
2874 Op->StartLoc = S;
2875 Op->EndLoc = S;
2876 return Op;
2877 }
2878
2879 static std::unique_ptr<ARMOperand> CreateCondCode(ARMCC::CondCodes CC,
2880 SMLoc S) {
2881 auto Op = make_unique<ARMOperand>(k_CondCode);
2882 Op->CC.Val = CC;
2883 Op->StartLoc = S;
2884 Op->EndLoc = S;
2885 return Op;
2886 }
2887
2888 static std::unique_ptr<ARMOperand> CreateCoprocNum(unsigned CopVal, SMLoc S) {
2889 auto Op = make_unique<ARMOperand>(k_CoprocNum);
2890 Op->Cop.Val = CopVal;
2891 Op->StartLoc = S;
2892 Op->EndLoc = S;
2893 return Op;
2894 }
2895
2896 static std::unique_ptr<ARMOperand> CreateCoprocReg(unsigned CopVal, SMLoc S) {
2897 auto Op = make_unique<ARMOperand>(k_CoprocReg);
2898 Op->Cop.Val = CopVal;
2899 Op->StartLoc = S;
2900 Op->EndLoc = S;
2901 return Op;
2902 }
2903
2904 static std::unique_ptr<ARMOperand> CreateCoprocOption(unsigned Val, SMLoc S,
2905 SMLoc E) {
2906 auto Op = make_unique<ARMOperand>(k_CoprocOption);
2907 Op->Cop.Val = Val;
2908 Op->StartLoc = S;
2909 Op->EndLoc = E;
2910 return Op;
2911 }
2912
2913 static std::unique_ptr<ARMOperand> CreateCCOut(unsigned RegNum, SMLoc S) {
2914 auto Op = make_unique<ARMOperand>(k_CCOut);
2915 Op->Reg.RegNum = RegNum;
2916 Op->StartLoc = S;
2917 Op->EndLoc = S;
2918 return Op;
2919 }
2920
2921 static std::unique_ptr<ARMOperand> CreateToken(StringRef Str, SMLoc S) {
2922 auto Op = make_unique<ARMOperand>(k_Token);
2923 Op->Tok.Data = Str.data();
2924 Op->Tok.Length = Str.size();
2925 Op->StartLoc = S;
2926 Op->EndLoc = S;
2927 return Op;
2928 }
2929
2930 static std::unique_ptr<ARMOperand> CreateReg(unsigned RegNum, SMLoc S,
2931 SMLoc E) {
2932 auto Op = make_unique<ARMOperand>(k_Register);
2933 Op->Reg.RegNum = RegNum;
2934 Op->StartLoc = S;
2935 Op->EndLoc = E;
2936 return Op;
2937 }
2938
2939 static std::unique_ptr<ARMOperand>
2940 CreateShiftedRegister(ARM_AM::ShiftOpc ShTy, unsigned SrcReg,
2941 unsigned ShiftReg, unsigned ShiftImm, SMLoc S,
2942 SMLoc E) {
2943 auto Op = make_unique<ARMOperand>(k_ShiftedRegister);
2944 Op->RegShiftedReg.ShiftTy = ShTy;
2945 Op->RegShiftedReg.SrcReg = SrcReg;
2946 Op->RegShiftedReg.ShiftReg = ShiftReg;
2947 Op->RegShiftedReg.ShiftImm = ShiftImm;
2948 Op->StartLoc = S;
2949 Op->EndLoc = E;
2950 return Op;
2951 }
2952
2953 static std::unique_ptr<ARMOperand>
2954 CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy, unsigned SrcReg,
2955 unsigned ShiftImm, SMLoc S, SMLoc E) {
2956 auto Op = make_unique<ARMOperand>(k_ShiftedImmediate);
2957 Op->RegShiftedImm.ShiftTy = ShTy;
2958 Op->RegShiftedImm.SrcReg = SrcReg;
2959 Op->RegShiftedImm.ShiftImm = ShiftImm;
2960 Op->StartLoc = S;
2961 Op->EndLoc = E;
2962 return Op;
2963 }
2964
2965 static std::unique_ptr<ARMOperand> CreateShifterImm(bool isASR, unsigned Imm,
2966 SMLoc S, SMLoc E) {
2967 auto Op = make_unique<ARMOperand>(k_ShifterImmediate);
2968 Op->ShifterImm.isASR = isASR;
2969 Op->ShifterImm.Imm = Imm;
2970 Op->StartLoc = S;
2971 Op->EndLoc = E;
2972 return Op;
2973 }
2974
2975 static std::unique_ptr<ARMOperand> CreateRotImm(unsigned Imm, SMLoc S,
2976 SMLoc E) {
2977 auto Op = make_unique<ARMOperand>(k_RotateImmediate);
2978 Op->RotImm.Imm = Imm;
2979 Op->StartLoc = S;
2980 Op->EndLoc = E;
2981 return Op;
2982 }
2983
2984 static std::unique_ptr<ARMOperand> CreateModImm(unsigned Bits, unsigned Rot,
2985 SMLoc S, SMLoc E) {
2986 auto Op = make_unique<ARMOperand>(k_ModifiedImmediate);
2987 Op->ModImm.Bits = Bits;
2988 Op->ModImm.Rot = Rot;
2989 Op->StartLoc = S;
2990 Op->EndLoc = E;
2991 return Op;
2992 }
2993
2994 static std::unique_ptr<ARMOperand>
2995 CreateConstantPoolImm(const MCExpr *Val, SMLoc S, SMLoc E) {
2996 auto Op = make_unique<ARMOperand>(k_ConstantPoolImmediate);
2997 Op->Imm.Val = Val;
2998 Op->StartLoc = S;
2999 Op->EndLoc = E;
3000 return Op;
3001 }
3002
3003 static std::unique_ptr<ARMOperand>
3004 CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) {
3005 auto Op = make_unique<ARMOperand>(k_BitfieldDescriptor);
3006 Op->Bitfield.LSB = LSB;
3007 Op->Bitfield.Width = Width;
3008 Op->StartLoc = S;
3009 Op->EndLoc = E;
3010 return Op;
3011 }
3012
3013 static std::unique_ptr<ARMOperand>
3014 CreateRegList(SmallVectorImpl<std::pair<unsigned, unsigned>> &Regs,
3015 SMLoc StartLoc, SMLoc EndLoc) {
3016 assert(Regs.size() > 0 && "RegList contains no registers?")(static_cast <bool> (Regs.size() > 0 && "RegList contains no registers?"
) ? void (0) : __assert_fail ("Regs.size() > 0 && \"RegList contains no registers?\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 3016, __extension__ __PRETTY_FUNCTION__))
;
3017 KindTy Kind = k_RegisterList;
3018
3019 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().second))
3020 Kind = k_DPRRegisterList;
3021 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
3022 contains(Regs.front().second))
3023 Kind = k_SPRRegisterList;
3024
3025 // Sort based on the register encoding values.
3026 array_pod_sort(Regs.begin(), Regs.end());
3027
3028 auto Op = make_unique<ARMOperand>(Kind);
3029 for (SmallVectorImpl<std::pair<unsigned, unsigned>>::const_iterator
3030 I = Regs.begin(), E = Regs.end(); I != E; ++I)
3031 Op->Registers.push_back(I->second);
3032 Op->StartLoc = StartLoc;
3033 Op->EndLoc = EndLoc;
3034 return Op;
3035 }
3036
3037 static std::unique_ptr<ARMOperand> CreateVectorList(unsigned RegNum,
3038 unsigned Count,
3039 bool isDoubleSpaced,
3040 SMLoc S, SMLoc E) {
3041 auto Op = make_unique<ARMOperand>(k_VectorList);
3042 Op->VectorList.RegNum = RegNum;
3043 Op->VectorList.Count = Count;
3044 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
3045 Op->StartLoc = S;
3046 Op->EndLoc = E;
3047 return Op;
3048 }
3049
3050 static std::unique_ptr<ARMOperand>
3051 CreateVectorListAllLanes(unsigned RegNum, unsigned Count, bool isDoubleSpaced,
3052 SMLoc S, SMLoc E) {
3053 auto Op = make_unique<ARMOperand>(k_VectorListAllLanes);
3054 Op->VectorList.RegNum = RegNum;
3055 Op->VectorList.Count = Count;
3056 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
3057 Op->StartLoc = S;
3058 Op->EndLoc = E;
3059 return Op;
3060 }
3061
3062 static std::unique_ptr<ARMOperand>
3063 CreateVectorListIndexed(unsigned RegNum, unsigned Count, unsigned Index,
3064 bool isDoubleSpaced, SMLoc S, SMLoc E) {
3065 auto Op = make_unique<ARMOperand>(k_VectorListIndexed);
3066 Op->VectorList.RegNum = RegNum;
3067 Op->VectorList.Count = Count;
3068 Op->VectorList.LaneIndex = Index;
3069 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
3070 Op->StartLoc = S;
3071 Op->EndLoc = E;
3072 return Op;
3073 }
3074
3075 static std::unique_ptr<ARMOperand>
3076 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
3077 auto Op = make_unique<ARMOperand>(k_VectorIndex);
3078 Op->VectorIndex.Val = Idx;
3079 Op->StartLoc = S;
3080 Op->EndLoc = E;
3081 return Op;
3082 }
3083
3084 static std::unique_ptr<ARMOperand> CreateImm(const MCExpr *Val, SMLoc S,
3085 SMLoc E) {
3086 auto Op = make_unique<ARMOperand>(k_Immediate);
3087 Op->Imm.Val = Val;
3088 Op->StartLoc = S;
3089 Op->EndLoc = E;
3090 return Op;
3091 }
3092
3093 static std::unique_ptr<ARMOperand>
3094 CreateMem(unsigned BaseRegNum, const MCConstantExpr *OffsetImm,
3095 unsigned OffsetRegNum, ARM_AM::ShiftOpc ShiftType,
3096 unsigned ShiftImm, unsigned Alignment, bool isNegative, SMLoc S,
3097 SMLoc E, SMLoc AlignmentLoc = SMLoc()) {
3098 auto Op = make_unique<ARMOperand>(k_Memory);
3099 Op->Memory.BaseRegNum = BaseRegNum;
3100 Op->Memory.OffsetImm = OffsetImm;
3101 Op->Memory.OffsetRegNum = OffsetRegNum;
3102 Op->Memory.ShiftType = ShiftType;
3103 Op->Memory.ShiftImm = ShiftImm;
3104 Op->Memory.Alignment = Alignment;
3105 Op->Memory.isNegative = isNegative;
3106 Op->StartLoc = S;
3107 Op->EndLoc = E;
3108 Op->AlignmentLoc = AlignmentLoc;
3109 return Op;
3110 }
3111
3112 static std::unique_ptr<ARMOperand>
3113 CreatePostIdxReg(unsigned RegNum, bool isAdd, ARM_AM::ShiftOpc ShiftTy,
3114 unsigned ShiftImm, SMLoc S, SMLoc E) {
3115 auto Op = make_unique<ARMOperand>(k_PostIndexRegister);
3116 Op->PostIdxReg.RegNum = RegNum;
3117 Op->PostIdxReg.isAdd = isAdd;
3118 Op->PostIdxReg.ShiftTy = ShiftTy;
3119 Op->PostIdxReg.ShiftImm = ShiftImm;
3120 Op->StartLoc = S;
3121 Op->EndLoc = E;
3122 return Op;
3123 }
3124
3125 static std::unique_ptr<ARMOperand> CreateMemBarrierOpt(ARM_MB::MemBOpt Opt,
3126 SMLoc S) {
3127 auto Op = make_unique<ARMOperand>(k_MemBarrierOpt);
3128 Op->MBOpt.Val = Opt;
3129 Op->StartLoc = S;
3130 Op->EndLoc = S;
3131 return Op;
3132 }
3133
3134 static std::unique_ptr<ARMOperand>
3135 CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S) {
3136 auto Op = make_unique<ARMOperand>(k_InstSyncBarrierOpt);
3137 Op->ISBOpt.Val = Opt;
3138 Op->StartLoc = S;
3139 Op->EndLoc = S;
3140 return Op;
3141 }
3142
3143 static std::unique_ptr<ARMOperand> CreateProcIFlags(ARM_PROC::IFlags IFlags,
3144 SMLoc S) {
3145 auto Op = make_unique<ARMOperand>(k_ProcIFlags);
3146 Op->IFlags.Val = IFlags;
3147 Op->StartLoc = S;
3148 Op->EndLoc = S;
3149 return Op;
3150 }
3151
3152 static std::unique_ptr<ARMOperand> CreateMSRMask(unsigned MMask, SMLoc S) {
3153 auto Op = make_unique<ARMOperand>(k_MSRMask);
3154 Op->MMask.Val = MMask;
3155 Op->StartLoc = S;
3156 Op->EndLoc = S;
3157 return Op;
3158 }
3159
3160 static std::unique_ptr<ARMOperand> CreateBankedReg(unsigned Reg, SMLoc S) {
3161 auto Op = make_unique<ARMOperand>(k_BankedReg);
3162 Op->BankedReg.Val = Reg;
3163 Op->StartLoc = S;
3164 Op->EndLoc = S;
3165 return Op;
3166 }
3167};
3168
3169} // end anonymous namespace.
3170
3171void ARMOperand::print(raw_ostream &OS) const {
3172 switch (Kind) {
3173 case k_CondCode:
3174 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
3175 break;
3176 case k_CCOut:
3177 OS << "<ccout " << getReg() << ">";
3178 break;
3179 case k_ITCondMask: {
3180 static const char *const MaskStr[] = {
3181 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
3182 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
3183 };
3184 assert((ITMask.Mask & 0xf) == ITMask.Mask)(static_cast <bool> ((ITMask.Mask & 0xf) == ITMask.
Mask) ? void (0) : __assert_fail ("(ITMask.Mask & 0xf) == ITMask.Mask"
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 3184, __extension__ __PRETTY_FUNCTION__))
;
3185 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
3186 break;
3187 }
3188 case k_CoprocNum:
3189 OS << "<coprocessor number: " << getCoproc() << ">";
3190 break;
3191 case k_CoprocReg:
3192 OS << "<coprocessor register: " << getCoproc() << ">";
3193 break;
3194 case k_CoprocOption:
3195 OS << "<coprocessor option: " << CoprocOption.Val << ">";
3196 break;
3197 case k_MSRMask:
3198 OS << "<mask: " << getMSRMask() << ">";
3199 break;
3200 case k_BankedReg:
3201 OS << "<banked reg: " << getBankedReg() << ">";
3202 break;
3203 case k_Immediate:
3204 OS << *getImm();
3205 break;
3206 case k_MemBarrierOpt:
3207 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt(), false) << ">";
3208 break;
3209 case k_InstSyncBarrierOpt:
3210 OS << "<ARM_ISB::" << InstSyncBOptToString(getInstSyncBarrierOpt()) << ">";
3211 break;
3212 case k_Memory:
3213 OS << "<memory "
3214 << " base:" << Memory.BaseRegNum;
3215 OS << ">";
3216 break;
3217 case k_PostIndexRegister:
3218 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
3219 << PostIdxReg.RegNum;
3220 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
3221 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
3222 << PostIdxReg.ShiftImm;
3223 OS << ">";
3224 break;
3225 case k_ProcIFlags: {
3226 OS << "<ARM_PROC::";
3227 unsigned IFlags = getProcIFlags();
3228 for (int i=2; i >= 0; --i)
3229 if (IFlags & (1 << i))
3230 OS << ARM_PROC::IFlagsToString(1 << i);
3231 OS << ">";
3232 break;
3233 }
3234 case k_Register:
3235 OS << "<register " << getReg() << ">";
3236 break;
3237 case k_ShifterImmediate:
3238 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
3239 << " #" << ShifterImm.Imm << ">";
3240 break;
3241 case k_ShiftedRegister:
3242 OS << "<so_reg_reg "
3243 << RegShiftedReg.SrcReg << " "
3244 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
3245 << " " << RegShiftedReg.ShiftReg << ">";
3246 break;
3247 case k_ShiftedImmediate:
3248 OS << "<so_reg_imm "
3249 << RegShiftedImm.SrcReg << " "
3250 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
3251 << " #" << RegShiftedImm.ShiftImm << ">";
3252 break;
3253 case k_RotateImmediate:
3254 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
3255 break;
3256 case k_ModifiedImmediate:
3257 OS << "<mod_imm #" << ModImm.Bits << ", #"
3258 << ModImm.Rot << ")>";
3259 break;
3260 case k_ConstantPoolImmediate:
3261 OS << "<constant_pool_imm #" << *getConstantPoolImm();
3262 break;
3263 case k_BitfieldDescriptor:
3264 OS << "<bitfield " << "lsb: " << Bitfield.LSB
3265 << ", width: " << Bitfield.Width << ">";
3266 break;
3267 case k_RegisterList:
3268 case k_DPRRegisterList:
3269 case k_SPRRegisterList: {
3270 OS << "<register_list ";
3271
3272 const SmallVectorImpl<unsigned> &RegList = getRegList();
3273 for (SmallVectorImpl<unsigned>::const_iterator
3274 I = RegList.begin(), E = RegList.end(); I != E; ) {
3275 OS << *I;
3276 if (++I < E) OS << ", ";
3277 }
3278
3279 OS << ">";
3280 break;
3281 }
3282 case k_VectorList:
3283 OS << "<vector_list " << VectorList.Count << " * "
3284 << VectorList.RegNum << ">";
3285 break;
3286 case k_VectorListAllLanes:
3287 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
3288 << VectorList.RegNum << ">";
3289 break;
3290 case k_VectorListIndexed:
3291 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
3292 << VectorList.Count << " * " << VectorList.RegNum << ">";
3293 break;
3294 case k_Token:
3295 OS << "'" << getToken() << "'";
3296 break;
3297 case k_VectorIndex:
3298 OS << "<vectorindex " << getVectorIndex() << ">";
3299 break;
3300 }
3301}
3302
3303/// @name Auto-generated Match Functions
3304/// {
3305
3306static unsigned MatchRegisterName(StringRef Name);
3307
3308/// }
3309
3310bool ARMAsmParser::ParseRegister(unsigned &RegNo,
3311 SMLoc &StartLoc, SMLoc &EndLoc) {
3312 const AsmToken &Tok = getParser().getTok();
3313 StartLoc = Tok.getLoc();
3314 EndLoc = Tok.getEndLoc();
3315 RegNo = tryParseRegister();
3316
3317 return (RegNo == (unsigned)-1);
3318}
3319
3320/// Try to parse a register name. The token must be an Identifier when called,
3321/// and if it is a register name the token is eaten and the register number is
3322/// returned. Otherwise return -1.
3323int ARMAsmParser::tryParseRegister() {
3324 MCAsmParser &Parser = getParser();
3325 const AsmToken &Tok = Parser.getTok();
3326 if (Tok.isNot(AsmToken::Identifier)) return -1;
3327
3328 std::string lowerCase = Tok.getString().lower();
3329 unsigned RegNum = MatchRegisterName(lowerCase);
3330 if (!RegNum) {
3331 RegNum = StringSwitch<unsigned>(lowerCase)
3332 .Case("r13", ARM::SP)
3333 .Case("r14", ARM::LR)
3334 .Case("r15", ARM::PC)
3335 .Case("ip", ARM::R12)
3336 // Additional register name aliases for 'gas' compatibility.
3337 .Case("a1", ARM::R0)
3338 .Case("a2", ARM::R1)
3339 .Case("a3", ARM::R2)
3340 .Case("a4", ARM::R3)
3341 .Case("v1", ARM::R4)
3342 .Case("v2", ARM::R5)
3343 .Case("v3", ARM::R6)
3344 .Case("v4", ARM::R7)
3345 .Case("v5", ARM::R8)
3346 .Case("v6", ARM::R9)
3347 .Case("v7", ARM::R10)
3348 .Case("v8", ARM::R11)
3349 .Case("sb", ARM::R9)
3350 .Case("sl", ARM::R10)
3351 .Case("fp", ARM::R11)
3352 .Default(0);
3353 }
3354 if (!RegNum) {
3355 // Check for aliases registered via .req. Canonicalize to lower case.
3356 // That's more consistent since register names are case insensitive, and
3357 // it's how the original entry was passed in from MC/MCParser/AsmParser.
3358 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
3359 // If no match, return failure.
3360 if (Entry == RegisterReqs.end())
3361 return -1;
3362 Parser.Lex(); // Eat identifier token.
3363 return Entry->getValue();
3364 }
3365
3366 // Some FPUs only have 16 D registers, so D16-D31 are invalid
3367 if (hasD16() && RegNum >= ARM::D16 && RegNum <= ARM::D31)
3368 return -1;
3369
3370 Parser.Lex(); // Eat identifier token.
3371
3372 return RegNum;
3373}
3374
3375// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
3376// If a recoverable error occurs, return 1. If an irrecoverable error
3377// occurs, return -1. An irrecoverable error is one where tokens have been
3378// consumed in the process of trying to parse the shifter (i.e., when it is
3379// indeed a shifter operand, but malformed).
3380int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) {
3381 MCAsmParser &Parser = getParser();
3382 SMLoc S = Parser.getTok().getLoc();
3383 const AsmToken &Tok = Parser.getTok();
3384 if (Tok.isNot(AsmToken::Identifier))
3385 return -1;
3386
3387 std::string lowerCase = Tok.getString().lower();
3388 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
3389 .Case("asl", ARM_AM::lsl)
3390 .Case("lsl", ARM_AM::lsl)
3391 .Case("lsr", ARM_AM::lsr)
3392 .Case("asr", ARM_AM::asr)
3393 .Case("ror", ARM_AM::ror)
3394 .Case("rrx", ARM_AM::rrx)
3395 .Default(ARM_AM::no_shift);
3396
3397 if (ShiftTy == ARM_AM::no_shift)
3398 return 1;
3399
3400 Parser.Lex(); // Eat the operator.
3401
3402 // The source register for the shift has already been added to the
3403 // operand list, so we need to pop it off and combine it into the shifted
3404 // register operand instead.
3405 std::unique_ptr<ARMOperand> PrevOp(
3406 (ARMOperand *)Operands.pop_back_val().release());
3407 if (!PrevOp->isReg())
3408 return Error(PrevOp->getStartLoc(), "shift must be of a register");
3409 int SrcReg = PrevOp->getReg();
3410
3411 SMLoc EndLoc;
3412 int64_t Imm = 0;
3413 int ShiftReg = 0;
3414 if (ShiftTy == ARM_AM::rrx) {
3415 // RRX Doesn't have an explicit shift amount. The encoder expects
3416 // the shift register to be the same as the source register. Seems odd,
3417 // but OK.
3418 ShiftReg = SrcReg;
3419 } else {
3420 // Figure out if this is shifted by a constant or a register (for non-RRX).
3421 if (Parser.getTok().is(AsmToken::Hash) ||
3422 Parser.getTok().is(AsmToken::Dollar)) {
3423 Parser.Lex(); // Eat hash.
3424 SMLoc ImmLoc = Parser.getTok().getLoc();
3425 const MCExpr *ShiftExpr = nullptr;
3426 if (getParser().parseExpression(ShiftExpr, EndLoc)) {
3427 Error(ImmLoc, "invalid immediate shift value");
3428 return -1;
3429 }
3430 // The expression must be evaluatable as an immediate.
3431 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
3432 if (!CE) {
3433 Error(ImmLoc, "invalid immediate shift value");
3434 return -1;
3435 }
3436 // Range check the immediate.
3437 // lsl, ror: 0 <= imm <= 31
3438 // lsr, asr: 0 <= imm <= 32
3439 Imm = CE->getValue();
3440 if (Imm < 0 ||
3441 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
3442 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
3443 Error(ImmLoc, "immediate shift value out of range");
3444 return -1;
3445 }
3446 // shift by zero is a nop. Always send it through as lsl.
3447 // ('as' compatibility)
3448 if (Imm == 0)
3449 ShiftTy = ARM_AM::lsl;
3450 } else if (Parser.getTok().is(AsmToken::Identifier)) {
3451 SMLoc L = Parser.getTok().getLoc();
3452 EndLoc = Parser.getTok().getEndLoc();
3453 ShiftReg = tryParseRegister();
3454 if (ShiftReg == -1) {
3455 Error(L, "expected immediate or register in shift operand");
3456 return -1;
3457 }
3458 } else {
3459 Error(Parser.getTok().getLoc(),
3460 "expected immediate or register in shift operand");
3461 return -1;
3462 }
3463 }
3464
3465 if (ShiftReg && ShiftTy != ARM_AM::rrx)
3466 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
3467 ShiftReg, Imm,
3468 S, EndLoc));
3469 else
3470 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
3471 S, EndLoc));
3472
3473 return 0;
3474}
3475
3476/// Try to parse a register name. The token must be an Identifier when called.
3477/// If it's a register, an AsmOperand is created. Another AsmOperand is created
3478/// if there is a "writeback". 'true' if it's not a register.
3479///
3480/// TODO this is likely to change to allow different register types and or to
3481/// parse for a specific register type.
3482bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) {
3483 MCAsmParser &Parser = getParser();
3484 SMLoc RegStartLoc = Parser.getTok().getLoc();
3485 SMLoc RegEndLoc = Parser.getTok().getEndLoc();
3486 int RegNo = tryParseRegister();
3487 if (RegNo == -1)
3488 return true;
3489
3490 Operands.push_back(ARMOperand::CreateReg(RegNo, RegStartLoc, RegEndLoc));
3491
3492 const AsmToken &ExclaimTok = Parser.getTok();
3493 if (ExclaimTok.is(AsmToken::Exclaim)) {
3494 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
3495 ExclaimTok.getLoc()));
3496 Parser.Lex(); // Eat exclaim token
3497 return false;
3498 }
3499
3500 // Also check for an index operand. This is only legal for vector registers,
3501 // but that'll get caught OK in operand matching, so we don't need to
3502 // explicitly filter everything else out here.
3503 if (Parser.getTok().is(AsmToken::LBrac)) {
3504 SMLoc SIdx = Parser.getTok().getLoc();
3505 Parser.Lex(); // Eat left bracket token.
3506
3507 const MCExpr *ImmVal;
3508 if (getParser().parseExpression(ImmVal))
3509 return true;
3510 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3511 if (!MCE)
3512 return TokError("immediate value expected for vector index");
3513
3514 if (Parser.getTok().isNot(AsmToken::RBrac))
3515 return Error(Parser.getTok().getLoc(), "']' expected");
3516
3517 SMLoc E = Parser.getTok().getEndLoc();
3518 Parser.Lex(); // Eat right bracket token.
3519
3520 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
3521 SIdx, E,
3522 getContext()));
3523 }
3524
3525 return false;
3526}
3527
3528/// MatchCoprocessorOperandName - Try to parse an coprocessor related
3529/// instruction with a symbolic operand name.
3530/// We accept "crN" syntax for GAS compatibility.
3531/// <operand-name> ::= <prefix><number>
3532/// If CoprocOp is 'c', then:
3533/// <prefix> ::= c | cr
3534/// If CoprocOp is 'p', then :
3535/// <prefix> ::= p
3536/// <number> ::= integer in range [0, 15]
3537static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
3538 // Use the same layout as the tablegen'erated register name matcher. Ugly,
3539 // but efficient.
3540 if (Name.size() < 2 || Name[0] != CoprocOp)
3541 return -1;
3542 Name = (Name[1] == 'r') ? Name.drop_front(2) : Name.drop_front();
3543
3544 switch (Name.size()) {
3545 default: return -1;
3546 case 1:
3547 switch (Name[0]) {
3548 default: return -1;
3549 case '0': return 0;
3550 case '1': return 1;
3551 case '2': return 2;
3552 case '3': return 3;
3553 case '4': return 4;
3554 case '5': return 5;
3555 case '6': return 6;
3556 case '7': return 7;
3557 case '8': return 8;
3558 case '9': return 9;
3559 }
3560 case 2:
3561 if (Name[0] != '1')
3562 return -1;
3563 switch (Name[1]) {
3564 default: return -1;
3565 // CP10 and CP11 are VFP/NEON and so vector instructions should be used.
3566 // However, old cores (v5/v6) did use them in that way.
3567 case '0': return 10;
3568 case '1': return 11;
3569 case '2': return 12;
3570 case '3': return 13;
3571 case '4': return 14;
3572 case '5': return 15;
3573 }
3574 }
3575}
3576
3577/// parseITCondCode - Try to parse a condition code for an IT instruction.
3578OperandMatchResultTy
3579ARMAsmParser::parseITCondCode(OperandVector &Operands) {
3580 MCAsmParser &Parser = getParser();
3581 SMLoc S = Parser.getTok().getLoc();
3582 const AsmToken &Tok = Parser.getTok();
3583 if (!Tok.is(AsmToken::Identifier))
3584 return MatchOperand_NoMatch;
3585 unsigned CC = ARMCondCodeFromString(Tok.getString());
3586 if (CC == ~0U)
3587 return MatchOperand_NoMatch;
3588 Parser.Lex(); // Eat the token.
3589
3590 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
3591
3592 return MatchOperand_Success;
3593}
3594
3595/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
3596/// token must be an Identifier when called, and if it is a coprocessor
3597/// number, the token is eaten and the operand is added to the operand list.
3598OperandMatchResultTy
3599ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) {
3600 MCAsmParser &Parser = getParser();
3601 SMLoc S = Parser.getTok().getLoc();
3602 const AsmToken &Tok = Parser.getTok();
3603 if (Tok.isNot(AsmToken::Identifier))
3604 return MatchOperand_NoMatch;
3605
3606 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
3607 if (Num == -1)
3608 return MatchOperand_NoMatch;
3609 // ARMv7 and v8 don't allow cp10/cp11 due to VFP/NEON specific instructions
3610 if ((hasV7Ops() || hasV8Ops()) && (Num == 10 || Num == 11))
3611 return MatchOperand_NoMatch;
3612
3613 Parser.Lex(); // Eat identifier token.
3614 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
3615 return MatchOperand_Success;
3616}
3617
3618/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
3619/// token must be an Identifier when called, and if it is a coprocessor
3620/// number, the token is eaten and the operand is added to the operand list.
3621OperandMatchResultTy
3622ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) {
3623 MCAsmParser &Parser = getParser();
3624 SMLoc S = Parser.getTok().getLoc();
3625 const AsmToken &Tok = Parser.getTok();
3626 if (Tok.isNot(AsmToken::Identifier))
3627 return MatchOperand_NoMatch;
3628
3629 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
3630 if (Reg == -1)
3631 return MatchOperand_NoMatch;
3632
3633 Parser.Lex(); // Eat identifier token.
3634 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
3635 return MatchOperand_Success;
3636}
3637
3638/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
3639/// coproc_option : '{' imm0_255 '}'
3640OperandMatchResultTy
3641ARMAsmParser::parseCoprocOptionOperand(OperandVector &Operands) {
3642 MCAsmParser &Parser = getParser();
3643 SMLoc S = Parser.getTok().getLoc();
3644
3645 // If this isn't a '{', this isn't a coprocessor immediate operand.
3646 if (Parser.getTok().isNot(AsmToken::LCurly))
3647 return MatchOperand_NoMatch;
3648 Parser.Lex(); // Eat the '{'
3649
3650 const MCExpr *Expr;
3651 SMLoc Loc = Parser.getTok().getLoc();
3652 if (getParser().parseExpression(Expr)) {
3653 Error(Loc, "illegal expression");
3654 return MatchOperand_ParseFail;
3655 }
3656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3657 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
3658 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
3659 return MatchOperand_ParseFail;
3660 }
3661 int Val = CE->getValue();
3662
3663 // Check for and consume the closing '}'
3664 if (Parser.getTok().isNot(AsmToken::RCurly))
3665 return MatchOperand_ParseFail;
3666 SMLoc E = Parser.getTok().getEndLoc();
3667 Parser.Lex(); // Eat the '}'
3668
3669 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
3670 return MatchOperand_Success;
3671}
3672
3673// For register list parsing, we need to map from raw GPR register numbering
3674// to the enumeration values. The enumeration values aren't sorted by
3675// register number due to our using "sp", "lr" and "pc" as canonical names.
3676static unsigned getNextRegister(unsigned Reg) {
3677 // If this is a GPR, we need to do it manually, otherwise we can rely
3678 // on the sort ordering of the enumeration since the other reg-classes
3679 // are sane.
3680 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
3681 return Reg + 1;
3682 switch(Reg) {
3683 default: llvm_unreachable("Invalid GPR number!")::llvm::llvm_unreachable_internal("Invalid GPR number!", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 3683)
;
3684 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
3685 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
3686 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
3687 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
3688 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
3689 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
3690 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
3691 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
3692 }
3693}
3694
3695/// Parse a register list.
3696bool ARMAsmParser::parseRegisterList(OperandVector &Operands) {
3697 MCAsmParser &Parser = getParser();
3698 if (Parser.getTok().isNot(AsmToken::LCurly))
3699 return TokError("Token is not a Left Curly Brace");
3700 SMLoc S = Parser.getTok().getLoc();
3701 Parser.Lex(); // Eat '{' token.
3702 SMLoc RegLoc = Parser.getTok().getLoc();
3703
3704 // Check the first register in the list to see what register class
3705 // this is a list of.
3706 int Reg = tryParseRegister();
3707 if (Reg == -1)
3708 return Error(RegLoc, "register expected");
3709
3710 // The reglist instructions have at most 16 registers, so reserve
3711 // space for that many.
3712 int EReg = 0;
3713 SmallVector<std::pair<unsigned, unsigned>, 16> Registers;
3714
3715 // Allow Q regs and just interpret them as the two D sub-registers.
3716 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3717 Reg = getDRegFromQReg(Reg);
3718 EReg = MRI->getEncodingValue(Reg);
3719 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3720 ++Reg;
3721 }
3722 const MCRegisterClass *RC;
3723 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
3724 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
3725 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
3726 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
3727 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
3728 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
3729 else
3730 return Error(RegLoc, "invalid register in register list");
3731
3732 // Store the register.
3733 EReg = MRI->getEncodingValue(Reg);
3734 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3735
3736 // This starts immediately after the first register token in the list,
3737 // so we can see either a comma or a minus (range separator) as a legal
3738 // next token.
3739 while (Parser.getTok().is(AsmToken::Comma) ||
3740 Parser.getTok().is(AsmToken::Minus)) {
3741 if (Parser.getTok().is(AsmToken::Minus)) {
3742 Parser.Lex(); // Eat the minus.
3743 SMLoc AfterMinusLoc = Parser.getTok().getLoc();
3744 int EndReg = tryParseRegister();
3745 if (EndReg == -1)
3746 return Error(AfterMinusLoc, "register expected");
3747 // Allow Q regs and just interpret them as the two D sub-registers.
3748 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3749 EndReg = getDRegFromQReg(EndReg) + 1;
3750 // If the register is the same as the start reg, there's nothing
3751 // more to do.
3752 if (Reg == EndReg)
3753 continue;
3754 // The register must be in the same register class as the first.
3755 if (!RC->contains(EndReg))
3756 return Error(AfterMinusLoc, "invalid register in register list");
3757 // Ranges must go from low to high.
3758 if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg))
3759 return Error(AfterMinusLoc, "bad range in register list");
3760
3761 // Add all the registers in the range to the register list.
3762 while (Reg != EndReg) {
3763 Reg = getNextRegister(Reg);
3764 EReg = MRI->getEncodingValue(Reg);
3765 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3766 }
3767 continue;
3768 }
3769 Parser.Lex(); // Eat the comma.
3770 RegLoc = Parser.getTok().getLoc();
3771 int OldReg = Reg;
3772 const AsmToken RegTok = Parser.getTok();
3773 Reg = tryParseRegister();
3774 if (Reg == -1)
3775 return Error(RegLoc, "register expected");
3776 // Allow Q regs and just interpret them as the two D sub-registers.
3777 bool isQReg = false;
3778 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3779 Reg = getDRegFromQReg(Reg);
3780 isQReg = true;
3781 }
3782 // The register must be in the same register class as the first.
3783 if (!RC->contains(Reg))
3784 return Error(RegLoc, "invalid register in register list");
3785 // List must be monotonically increasing.
3786 if (MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) {
3787 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
3788 Warning(RegLoc, "register list not in ascending order");
3789 else
3790 return Error(RegLoc, "register list not in ascending order");
3791 }
3792 if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) {
3793 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
3794 ") in register list");
3795 continue;
3796 }
3797 // VFP register lists must also be contiguous.
3798 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
3799 Reg != OldReg + 1)
3800 return Error(RegLoc, "non-contiguous register range");
3801 EReg = MRI->getEncodingValue(Reg);
3802 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3803 if (isQReg) {
3804 EReg = MRI->getEncodingValue(++Reg);
3805 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3806 }
3807 }
3808
3809 if (Parser.getTok().isNot(AsmToken::RCurly))
3810 return Error(Parser.getTok().getLoc(), "'}' expected");
3811 SMLoc E = Parser.getTok().getEndLoc();
3812 Parser.Lex(); // Eat '}' token.
3813
3814 // Push the register list operand.
3815 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
3816
3817 // The ARM system instruction variants for LDM/STM have a '^' token here.
3818 if (Parser.getTok().is(AsmToken::Caret)) {
3819 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
3820 Parser.Lex(); // Eat '^' token.
3821 }
3822
3823 return false;
3824}
3825
3826// Helper function to parse the lane index for vector lists.
3827OperandMatchResultTy ARMAsmParser::
3828parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) {
3829 MCAsmParser &Parser = getParser();
3830 Index = 0; // Always return a defined index value.
3831 if (Parser.getTok().is(AsmToken::LBrac)) {
3832 Parser.Lex(); // Eat the '['.
3833 if (Parser.getTok().is(AsmToken::RBrac)) {
3834 // "Dn[]" is the 'all lanes' syntax.
3835 LaneKind = AllLanes;
3836 EndLoc = Parser.getTok().getEndLoc();
3837 Parser.Lex(); // Eat the ']'.
3838 return MatchOperand_Success;
3839 }
3840
3841 // There's an optional '#' token here. Normally there wouldn't be, but
3842 // inline assemble puts one in, and it's friendly to accept that.
3843 if (Parser.getTok().is(AsmToken::Hash))
3844 Parser.Lex(); // Eat '#' or '$'.
3845
3846 const MCExpr *LaneIndex;
3847 SMLoc Loc = Parser.getTok().getLoc();
3848 if (getParser().parseExpression(LaneIndex)) {
3849 Error(Loc, "illegal expression");
3850 return MatchOperand_ParseFail;
3851 }
3852 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
3853 if (!CE) {
3854 Error(Loc, "lane index must be empty or an integer");
3855 return MatchOperand_ParseFail;
3856 }
3857 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3858 Error(Parser.getTok().getLoc(), "']' expected");
3859 return MatchOperand_ParseFail;
3860 }
3861 EndLoc = Parser.getTok().getEndLoc();
3862 Parser.Lex(); // Eat the ']'.
3863 int64_t Val = CE->getValue();
3864
3865 // FIXME: Make this range check context sensitive for .8, .16, .32.
3866 if (Val < 0 || Val > 7) {
3867 Error(Parser.getTok().getLoc(), "lane index out of range");
3868 return MatchOperand_ParseFail;
3869 }
3870 Index = Val;
3871 LaneKind = IndexedLane;
3872 return MatchOperand_Success;
3873 }
3874 LaneKind = NoLanes;
3875 return MatchOperand_Success;
3876}
3877
3878// parse a vector register list
3879OperandMatchResultTy
3880ARMAsmParser::parseVectorList(OperandVector &Operands) {
3881 MCAsmParser &Parser = getParser();
3882 VectorLaneTy LaneKind;
3883 unsigned LaneIndex;
3884 SMLoc S = Parser.getTok().getLoc();
3885 // As an extension (to match gas), support a plain D register or Q register
3886 // (without encosing curly braces) as a single or double entry list,
3887 // respectively.
3888 if (Parser.getTok().is(AsmToken::Identifier)) {
3889 SMLoc E = Parser.getTok().getEndLoc();
3890 int Reg = tryParseRegister();
3891 if (Reg == -1)
3892 return MatchOperand_NoMatch;
3893 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
3894 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E);
3895 if (Res != MatchOperand_Success)
3896 return Res;
3897 switch (LaneKind) {
3898 case NoLanes:
3899 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
3900 break;
3901 case AllLanes:
3902 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3903 S, E));
3904 break;
3905 case IndexedLane:
3906 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
3907 LaneIndex,
3908 false, S, E));
3909 break;
3910 }
3911 return MatchOperand_Success;
3912 }
3913 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3914 Reg = getDRegFromQReg(Reg);
3915 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E);
3916 if (Res != MatchOperand_Success)
3917 return Res;
3918 switch (LaneKind) {
3919 case NoLanes:
3920 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3921 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
3922 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
3923 break;
3924 case AllLanes:
3925 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3926 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
3927 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3928 S, E));
3929 break;
3930 case IndexedLane:
3931 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
3932 LaneIndex,
3933 false, S, E));
3934 break;
3935 }
3936 return MatchOperand_Success;
3937 }
3938 Error(S, "vector register expected");
3939 return MatchOperand_ParseFail;
3940 }
3941
3942 if (Parser.getTok().isNot(AsmToken::LCurly))
3943 return MatchOperand_NoMatch;
3944
3945 Parser.Lex(); // Eat '{' token.
3946 SMLoc RegLoc = Parser.getTok().getLoc();
3947
3948 int Reg = tryParseRegister();
3949 if (Reg == -1) {
3950 Error(RegLoc, "register expected");
3951 return MatchOperand_ParseFail;
3952 }
3953 unsigned Count = 1;
3954 int Spacing = 0;
3955 unsigned FirstReg = Reg;
3956 // The list is of D registers, but we also allow Q regs and just interpret
3957 // them as the two D sub-registers.
3958 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3959 FirstReg = Reg = getDRegFromQReg(Reg);
3960 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3961 // it's ambiguous with four-register single spaced.
3962 ++Reg;
3963 ++Count;
3964 }
3965
3966 SMLoc E;
3967 if (parseVectorLane(LaneKind, LaneIndex, E) != MatchOperand_Success)
3968 return MatchOperand_ParseFail;
3969
3970 while (Parser.getTok().is(AsmToken::Comma) ||
3971 Parser.getTok().is(AsmToken::Minus)) {
3972 if (Parser.getTok().is(AsmToken::Minus)) {
3973 if (!Spacing)
3974 Spacing = 1; // Register range implies a single spaced list.
3975 else if (Spacing == 2) {
3976 Error(Parser.getTok().getLoc(),
3977 "sequential registers in double spaced list");
3978 return MatchOperand_ParseFail;
3979 }
3980 Parser.Lex(); // Eat the minus.
3981 SMLoc AfterMinusLoc = Parser.getTok().getLoc();
3982 int EndReg = tryParseRegister();
3983 if (EndReg == -1) {
3984 Error(AfterMinusLoc, "register expected");
3985 return MatchOperand_ParseFail;
3986 }
3987 // Allow Q regs and just interpret them as the two D sub-registers.
3988 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3989 EndReg = getDRegFromQReg(EndReg) + 1;
3990 // If the register is the same as the start reg, there's nothing
3991 // more to do.
3992 if (Reg == EndReg)
3993 continue;
3994 // The register must be in the same register class as the first.
3995 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3996 Error(AfterMinusLoc, "invalid register in register list");
3997 return MatchOperand_ParseFail;
3998 }
3999 // Ranges must go from low to high.
4000 if (Reg > EndReg) {
4001 Error(AfterMinusLoc, "bad range in register list");
4002 return MatchOperand_ParseFail;
4003 }
4004 // Parse the lane specifier if present.
4005 VectorLaneTy NextLaneKind;
4006 unsigned NextLaneIndex;
4007 if (parseVectorLane(NextLaneKind, NextLaneIndex, E) !=
4008 MatchOperand_Success)
4009 return MatchOperand_ParseFail;
4010 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
4011 Error(AfterMinusLoc, "mismatched lane index in register list");
4012 return MatchOperand_ParseFail;
4013 }
4014
4015 // Add all the registers in the range to the register list.
4016 Count += EndReg - Reg;
4017 Reg = EndReg;
4018 continue;
4019 }
4020 Parser.Lex(); // Eat the comma.
4021 RegLoc = Parser.getTok().getLoc();
4022 int OldReg = Reg;
4023 Reg = tryParseRegister();
4024 if (Reg == -1) {
4025 Error(RegLoc, "register expected");
4026 return MatchOperand_ParseFail;
4027 }
4028 // vector register lists must be contiguous.
4029 // It's OK to use the enumeration values directly here rather, as the
4030 // VFP register classes have the enum sorted properly.
4031 //
4032 // The list is of D registers, but we also allow Q regs and just interpret
4033 // them as the two D sub-registers.
4034 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
4035 if (!Spacing)
4036 Spacing = 1; // Register range implies a single spaced list.
4037 else if (Spacing == 2) {
4038 Error(RegLoc,
4039 "invalid register in double-spaced list (must be 'D' register')");
4040 return MatchOperand_ParseFail;
4041 }
4042 Reg = getDRegFromQReg(Reg);
4043 if (Reg != OldReg + 1) {
4044 Error(RegLoc, "non-contiguous register range");
4045 return MatchOperand_ParseFail;
4046 }
4047 ++Reg;
4048 Count += 2;
4049 // Parse the lane specifier if present.
4050 VectorLaneTy NextLaneKind;
4051 unsigned NextLaneIndex;
4052 SMLoc LaneLoc = Parser.getTok().getLoc();
4053 if (parseVectorLane(NextLaneKind, NextLaneIndex, E) !=
4054 MatchOperand_Success)
4055 return MatchOperand_ParseFail;
4056 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
4057 Error(LaneLoc, "mismatched lane index in register list");
4058 return MatchOperand_ParseFail;
4059 }
4060 continue;
4061 }
4062 // Normal D register.
4063 // Figure out the register spacing (single or double) of the list if
4064 // we don't know it already.
4065 if (!Spacing)
4066 Spacing = 1 + (Reg == OldReg + 2);
4067
4068 // Just check that it's contiguous and keep going.
4069 if (Reg != OldReg + Spacing) {
4070 Error(RegLoc, "non-contiguous register range");
4071 return MatchOperand_ParseFail;
4072 }
4073 ++Count;
4074 // Parse the lane specifier if present.
4075 VectorLaneTy NextLaneKind;
4076 unsigned NextLaneIndex;
4077 SMLoc EndLoc = Parser.getTok().getLoc();
4078 if (parseVectorLane(NextLaneKind, NextLaneIndex, E) != MatchOperand_Success)
4079 return MatchOperand_ParseFail;
4080 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
4081 Error(EndLoc, "mismatched lane index in register list");
4082 return MatchOperand_ParseFail;
4083 }
4084 }
4085
4086 if (Parser.getTok().isNot(AsmToken::RCurly)) {
4087 Error(Parser.getTok().getLoc(), "'}' expected");
4088 return MatchOperand_ParseFail;
4089 }
4090 E = Parser.getTok().getEndLoc();
4091 Parser.Lex(); // Eat '}' token.
4092
4093 switch (LaneKind) {
4094 case NoLanes:
4095 // Two-register operands have been converted to the
4096 // composite register classes.
4097 if (Count == 2) {
4098 const MCRegisterClass *RC = (Spacing == 1) ?
4099 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
4100 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
4101 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
4102 }
4103 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
4104 (Spacing == 2), S, E));
4105 break;
4106 case AllLanes:
4107 // Two-register operands have been converted to the
4108 // composite register classes.
4109 if (Count == 2) {
4110 const MCRegisterClass *RC = (Spacing == 1) ?
4111 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
4112 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
4113 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
4114 }
4115 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
4116 (Spacing == 2),
4117 S, E));
4118 break;
4119 case IndexedLane:
4120 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
4121 LaneIndex,
4122 (Spacing == 2),
4123 S, E));
4124 break;
4125 }
4126 return MatchOperand_Success;
4127}
4128
4129/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
4130OperandMatchResultTy
4131ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) {
4132 MCAsmParser &Parser = getParser();
4133 SMLoc S = Parser.getTok().getLoc();
4134 const AsmToken &Tok = Parser.getTok();
4135 unsigned Opt;
4136
4137 if (Tok.is(AsmToken::Identifier)) {
4138 StringRef OptStr = Tok.getString();
4139
4140 Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()).lower())
4141 .Case("sy", ARM_MB::SY)
4142 .Case("st", ARM_MB::ST)
4143 .Case("ld", ARM_MB::LD)
4144 .Case("sh", ARM_MB::ISH)
4145 .Case("ish", ARM_MB::ISH)
4146 .Case("shst", ARM_MB::ISHST)
4147 .Case("ishst", ARM_MB::ISHST)
4148 .Case("ishld", ARM_MB::ISHLD)
4149 .Case("nsh", ARM_MB::NSH)
4150 .Case("un", ARM_MB::NSH)
4151 .Case("nshst", ARM_MB::NSHST)
4152 .Case("nshld", ARM_MB::NSHLD)
4153 .Case("unst", ARM_MB::NSHST)
4154 .Case("osh", ARM_MB::OSH)
4155 .Case("oshst", ARM_MB::OSHST)
4156 .Case("oshld", ARM_MB::OSHLD)
4157 .Default(~0U);
4158
4159 // ishld, oshld, nshld and ld are only available from ARMv8.
4160 if (!hasV8Ops() && (Opt == ARM_MB::ISHLD || Opt == ARM_MB::OSHLD ||
4161 Opt == ARM_MB::NSHLD || Opt == ARM_MB::LD))
4162 Opt = ~0U;
4163
4164 if (Opt == ~0U)
4165 return MatchOperand_NoMatch;
4166
4167 Parser.Lex(); // Eat identifier token.
4168 } else if (Tok.is(AsmToken::Hash) ||
4169 Tok.is(AsmToken::Dollar) ||
4170 Tok.is(AsmToken::Integer)) {
4171 if (Parser.getTok().isNot(AsmToken::Integer))
4172 Parser.Lex(); // Eat '#' or '$'.
4173 SMLoc Loc = Parser.getTok().getLoc();
4174
4175 const MCExpr *MemBarrierID;
4176 if (getParser().parseExpression(MemBarrierID)) {
4177 Error(Loc, "illegal expression");
4178 return MatchOperand_ParseFail;
4179 }
4180
4181 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(MemBarrierID);
4182 if (!CE) {
4183 Error(Loc, "constant expression expected");
4184 return MatchOperand_ParseFail;
4185 }
4186
4187 int Val = CE->getValue();
4188 if (Val & ~0xf) {
4189 Error(Loc, "immediate value out of range");
4190 return MatchOperand_ParseFail;
4191 }
4192
4193 Opt = ARM_MB::RESERVED_0 + Val;
4194 } else
4195 return MatchOperand_ParseFail;
4196
4197 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
4198 return MatchOperand_Success;
4199}
4200
4201/// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options.
4202OperandMatchResultTy
4203ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) {
4204 MCAsmParser &Parser = getParser();
4205 SMLoc S = Parser.getTok().getLoc();
4206 const AsmToken &Tok = Parser.getTok();
4207 unsigned Opt;
4208
4209 if (Tok.is(AsmToken::Identifier)) {
4210 StringRef OptStr = Tok.getString();
4211
4212 if (OptStr.equals_lower("sy"))
4213 Opt = ARM_ISB::SY;
4214 else
4215 return MatchOperand_NoMatch;
4216
4217 Parser.Lex(); // Eat identifier token.
4218 } else if (Tok.is(AsmToken::Hash) ||
4219 Tok.is(AsmToken::Dollar) ||
4220 Tok.is(AsmToken::Integer)) {
4221 if (Parser.getTok().isNot(AsmToken::Integer))
4222 Parser.Lex(); // Eat '#' or '$'.
4223 SMLoc Loc = Parser.getTok().getLoc();
4224
4225 const MCExpr *ISBarrierID;
4226 if (getParser().parseExpression(ISBarrierID)) {
4227 Error(Loc, "illegal expression");
4228 return MatchOperand_ParseFail;
4229 }
4230
4231 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ISBarrierID);
4232 if (!CE) {
4233 Error(Loc, "constant expression expected");
4234 return MatchOperand_ParseFail;
4235 }
4236
4237 int Val = CE->getValue();
4238 if (Val & ~0xf) {
4239 Error(Loc, "immediate value out of range");
4240 return MatchOperand_ParseFail;
4241 }
4242
4243 Opt = ARM_ISB::RESERVED_0 + Val;
4244 } else
4245 return MatchOperand_ParseFail;
4246
4247 Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt(
4248 (ARM_ISB::InstSyncBOpt)Opt, S));
4249 return MatchOperand_Success;
4250}
4251
4252
4253/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
4254OperandMatchResultTy
4255ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) {
4256 MCAsmParser &Parser = getParser();
4257 SMLoc S = Parser.getTok().getLoc();
4258 const AsmToken &Tok = Parser.getTok();
4259 if (!Tok.is(AsmToken::Identifier))
4260 return MatchOperand_NoMatch;
4261 StringRef IFlagsStr = Tok.getString();
4262
4263 // An iflags string of "none" is interpreted to mean that none of the AIF
4264 // bits are set. Not a terribly useful instruction, but a valid encoding.
4265 unsigned IFlags = 0;
4266 if (IFlagsStr != "none") {
4267 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
4268 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1).lower())
4269 .Case("a", ARM_PROC::A)
4270 .Case("i", ARM_PROC::I)
4271 .Case("f", ARM_PROC::F)
4272 .Default(~0U);
4273
4274 // If some specific iflag is already set, it means that some letter is
4275 // present more than once, this is not acceptable.
4276 if (Flag == ~0U || (IFlags & Flag))
4277 return MatchOperand_NoMatch;
4278
4279 IFlags |= Flag;
4280 }
4281 }
4282
4283 Parser.Lex(); // Eat identifier token.
4284 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
4285 return MatchOperand_Success;
4286}
4287
4288/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
4289OperandMatchResultTy
4290ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) {
4291 MCAsmParser &Parser = getParser();
4292 SMLoc S = Parser.getTok().getLoc();
4293 const AsmToken &Tok = Parser.getTok();
4294
4295 if (Tok.is(AsmToken::Integer)) {
4296 int64_t Val = Tok.getIntVal();
4297 if (Val > 255 || Val < 0) {
4298 return MatchOperand_NoMatch;
4299 }
4300 unsigned SYSmvalue = Val & 0xFF;
4301 Parser.Lex();
4302 Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S));
4303 return MatchOperand_Success;
4304 }
4305
4306 if (!Tok.is(AsmToken::Identifier))
4307 return MatchOperand_NoMatch;
4308 StringRef Mask = Tok.getString();
4309
4310 if (isMClass()) {
4311 auto TheReg = ARMSysReg::lookupMClassSysRegByName(Mask.lower());
4312 if (!TheReg || !TheReg->hasRequiredFeatures(getSTI().getFeatureBits()))
4313 return MatchOperand_NoMatch;
4314
4315 unsigned SYSmvalue = TheReg->Encoding & 0xFFF;
4316
4317 Parser.Lex(); // Eat identifier token.
4318 Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S));
4319 return MatchOperand_Success;
4320 }
4321
4322 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
4323 size_t Start = 0, Next = Mask.find('_');
4324 StringRef Flags = "";
4325 std::string SpecReg = Mask.slice(Start, Next).lower();
4326 if (Next != StringRef::npos)
4327 Flags = Mask.slice(Next+1, Mask.size());
4328
4329 // FlagsVal contains the complete mask:
4330 // 3-0: Mask
4331 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
4332 unsigned FlagsVal = 0;
4333
4334 if (SpecReg == "apsr") {
4335 FlagsVal = StringSwitch<unsigned>(Flags)
4336 .Case("nzcvq", 0x8) // same as CPSR_f
4337 .Case("g", 0x4) // same as CPSR_s
4338 .Case("nzcvqg", 0xc) // same as CPSR_fs
4339 .Default(~0U);
4340
4341 if (FlagsVal == ~0U) {
4342 if (!Flags.empty())
4343 return MatchOperand_NoMatch;
4344 else
4345 FlagsVal = 8; // No flag
4346 }
4347 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
4348 // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
4349 if (Flags == "all" || Flags == "")
4350 Flags = "fc";
4351 for (int i = 0, e = Flags.size(); i != e; ++i) {
4352 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
4353 .Case("c", 1)
4354 .Case("x", 2)
4355 .Case("s", 4)
4356 .Case("f", 8)
4357 .Default(~0U);
4358
4359 // If some specific flag is already set, it means that some letter is
4360 // present more than once, this is not acceptable.
4361 if (Flag == ~0U || (FlagsVal & Flag))
4362 return MatchOperand_NoMatch;
4363 FlagsVal |= Flag;
4364 }
4365 } else // No match for special register.
4366 return MatchOperand_NoMatch;
4367
4368 // Special register without flags is NOT equivalent to "fc" flags.
4369 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
4370 // two lines would enable gas compatibility at the expense of breaking
4371 // round-tripping.
4372 //
4373 // if (!FlagsVal)
4374 // FlagsVal = 0x9;
4375
4376 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
4377 if (SpecReg == "spsr")
4378 FlagsVal |= 16;
4379
4380 Parser.Lex(); // Eat identifier token.
4381 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
4382 return MatchOperand_Success;
4383}
4384
4385/// parseBankedRegOperand - Try to parse a banked register (e.g. "lr_irq") for
4386/// use in the MRS/MSR instructions added to support virtualization.
4387OperandMatchResultTy
4388ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) {
4389 MCAsmParser &Parser = getParser();
4390 SMLoc S = Parser.getTok().getLoc();
4391 const AsmToken &Tok = Parser.getTok();
4392 if (!Tok.is(AsmToken::Identifier))
4393 return MatchOperand_NoMatch;
4394 StringRef RegName = Tok.getString();
4395
4396 auto TheReg = ARMBankedReg::lookupBankedRegByName(RegName.lower());
4397 if (!TheReg)
4398 return MatchOperand_NoMatch;
4399 unsigned Encoding = TheReg->Encoding;
4400
4401 Parser.Lex(); // Eat identifier token.
4402 Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S));
4403 return MatchOperand_Success;
4404}
4405
4406OperandMatchResultTy
4407ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, int Low,
4408 int High) {
4409 MCAsmParser &Parser = getParser();
4410 const AsmToken &Tok = Parser.getTok();
4411 if (Tok.isNot(AsmToken::Identifier)) {
4412 Error(Parser.getTok().getLoc(), Op + " operand expected.");
4413 return MatchOperand_ParseFail;
4414 }
4415 StringRef ShiftName = Tok.getString();
4416 std::string LowerOp = Op.lower();
4417 std::string UpperOp = Op.upper();
4418 if (ShiftName != LowerOp && ShiftName != UpperOp) {
4419 Error(Parser.getTok().getLoc(), Op + " operand expected.");
4420 return MatchOperand_ParseFail;
4421 }
4422 Parser.Lex(); // Eat shift type token.
4423
4424 // There must be a '#' and a shift amount.
4425 if (Parser.getTok().isNot(AsmToken::Hash) &&
4426 Parser.getTok().isNot(AsmToken::Dollar)) {
4427 Error(Parser.getTok().getLoc(), "'#' expected");
4428 return MatchOperand_ParseFail;
4429 }
4430 Parser.Lex(); // Eat hash token.
4431
4432 const MCExpr *ShiftAmount;
4433 SMLoc Loc = Parser.getTok().getLoc();
4434 SMLoc EndLoc;
4435 if (getParser().parseExpression(ShiftAmount, EndLoc)) {
4436 Error(Loc, "illegal expression");
4437 return MatchOperand_ParseFail;
4438 }
4439 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
4440 if (!CE) {
4441 Error(Loc, "constant expression expected");
4442 return MatchOperand_ParseFail;
4443 }
4444 int Val = CE->getValue();
4445 if (Val < Low || Val > High) {
4446 Error(Loc, "immediate value out of range");
4447 return MatchOperand_ParseFail;
4448 }
4449
4450 Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc));
4451
4452 return MatchOperand_Success;
4453}
4454
4455OperandMatchResultTy
4456ARMAsmParser::parseSetEndImm(OperandVector &Operands) {
4457 MCAsmParser &Parser = getParser();
4458 const AsmToken &Tok = Parser.getTok();
4459 SMLoc S = Tok.getLoc();
4460 if (Tok.isNot(AsmToken::Identifier)) {
4461 Error(S, "'be' or 'le' operand expected");
4462 return MatchOperand_ParseFail;
4463 }
4464 int Val = StringSwitch<int>(Tok.getString().lower())
4465 .Case("be", 1)
4466 .Case("le", 0)
4467 .Default(-1);
4468 Parser.Lex(); // Eat the token.
4469
4470 if (Val == -1) {
4471 Error(S, "'be' or 'le' operand expected");
4472 return MatchOperand_ParseFail;
4473 }
4474 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::create(Val,
4475 getContext()),
4476 S, Tok.getEndLoc()));
4477 return MatchOperand_Success;
4478}
4479
4480/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
4481/// instructions. Legal values are:
4482/// lsl #n 'n' in [0,31]
4483/// asr #n 'n' in [1,32]
4484/// n == 32 encoded as n == 0.
4485OperandMatchResultTy
4486ARMAsmParser::parseShifterImm(OperandVector &Operands) {
4487 MCAsmParser &Parser = getParser();
4488 const AsmToken &Tok = Parser.getTok();
4489 SMLoc S = Tok.getLoc();
4490 if (Tok.isNot(AsmToken::Identifier)) {
4491 Error(S, "shift operator 'asr' or 'lsl' expected");
4492 return MatchOperand_ParseFail;
4493 }
4494 StringRef ShiftName = Tok.getString();
4495 bool isASR;
4496 if (ShiftName == "lsl" || ShiftName == "LSL")
4497 isASR = false;
4498 else if (ShiftName == "asr" || ShiftName == "ASR")
4499 isASR = true;
4500 else {
4501 Error(S, "shift operator 'asr' or 'lsl' expected");
4502 return MatchOperand_ParseFail;
4503 }
4504 Parser.Lex(); // Eat the operator.
4505
4506 // A '#' and a shift amount.
4507 if (Parser.getTok().isNot(AsmToken::Hash) &&
4508 Parser.getTok().isNot(AsmToken::Dollar)) {
4509 Error(Parser.getTok().getLoc(), "'#' expected");
4510 return MatchOperand_ParseFail;
4511 }
4512 Parser.Lex(); // Eat hash token.
4513 SMLoc ExLoc = Parser.getTok().getLoc();
4514
4515 const MCExpr *ShiftAmount;
4516 SMLoc EndLoc;
4517 if (getParser().parseExpression(ShiftAmount, EndLoc)) {
4518 Error(ExLoc, "malformed shift expression");
4519 return MatchOperand_ParseFail;
4520 }
4521 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
4522 if (!CE) {
4523 Error(ExLoc, "shift amount must be an immediate");
4524 return MatchOperand_ParseFail;
4525 }
4526
4527 int64_t Val = CE->getValue();
4528 if (isASR) {
4529 // Shift amount must be in [1,32]
4530 if (Val < 1 || Val > 32) {
4531 Error(ExLoc, "'asr' shift amount must be in range [1,32]");
4532 return MatchOperand_ParseFail;
4533 }
4534 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
4535 if (isThumb() && Val == 32) {
4536 Error(ExLoc, "'asr #32' shift amount not allowed in Thumb mode");
4537 return MatchOperand_ParseFail;
4538 }
4539 if (Val == 32) Val = 0;
4540 } else {
4541 // Shift amount must be in [1,32]
4542 if (Val < 0 || Val > 31) {
4543 Error(ExLoc, "'lsr' shift amount must be in range [0,31]");
4544 return MatchOperand_ParseFail;
4545 }
4546 }
4547
4548 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc));
4549
4550 return MatchOperand_Success;
4551}
4552
4553/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
4554/// of instructions. Legal values are:
4555/// ror #n 'n' in {0, 8, 16, 24}
4556OperandMatchResultTy
4557ARMAsmParser::parseRotImm(OperandVector &Operands) {
4558 MCAsmParser &Parser = getParser();
4559 const AsmToken &Tok = Parser.getTok();
4560 SMLoc S = Tok.getLoc();
4561 if (Tok.isNot(AsmToken::Identifier))
4562 return MatchOperand_NoMatch;
4563 StringRef ShiftName = Tok.getString();
4564 if (ShiftName != "ror" && ShiftName != "ROR")
4565 return MatchOperand_NoMatch;
4566 Parser.Lex(); // Eat the operator.
4567
4568 // A '#' and a rotate amount.
4569 if (Parser.getTok().isNot(AsmToken::Hash) &&
4570 Parser.getTok().isNot(AsmToken::Dollar)) {
4571 Error(Parser.getTok().getLoc(), "'#' expected");
4572 return MatchOperand_ParseFail;
4573 }
4574 Parser.Lex(); // Eat hash token.
4575 SMLoc ExLoc = Parser.getTok().getLoc();
4576
4577 const MCExpr *ShiftAmount;
4578 SMLoc EndLoc;
4579 if (getParser().parseExpression(ShiftAmount, EndLoc)) {
4580 Error(ExLoc, "malformed rotate expression");
4581 return MatchOperand_ParseFail;
4582 }
4583 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
4584 if (!CE) {
4585 Error(ExLoc, "rotate amount must be an immediate");
4586 return MatchOperand_ParseFail;
4587 }
4588
4589 int64_t Val = CE->getValue();
4590 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
4591 // normally, zero is represented in asm by omitting the rotate operand
4592 // entirely.
4593 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
4594 Error(ExLoc, "'ror' rotate amount must be 8, 16, or 24");
4595 return MatchOperand_ParseFail;
4596 }
4597
4598 Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc));
4599
4600 return MatchOperand_Success;
4601}
4602
4603OperandMatchResultTy
4604ARMAsmParser::parseModImm(OperandVector &Operands) {
4605 MCAsmParser &Parser = getParser();
4606 MCAsmLexer &Lexer = getLexer();
4607 int64_t Imm1, Imm2;
4608
4609 SMLoc S = Parser.getTok().getLoc();
4610
4611 // 1) A mod_imm operand can appear in the place of a register name:
4612 // add r0, #mod_imm
4613 // add r0, r0, #mod_imm
4614 // to correctly handle the latter, we bail out as soon as we see an
4615 // identifier.
4616 //
4617 // 2) Similarly, we do not want to parse into complex operands:
4618 // mov r0, #mod_imm
4619 // mov r0, :lower16:(_foo)
4620 if (Parser.getTok().is(AsmToken::Identifier) ||
4621 Parser.getTok().is(AsmToken::Colon))
4622 return MatchOperand_NoMatch;
4623
4624 // Hash (dollar) is optional as per the ARMARM
4625 if (Parser.getTok().is(AsmToken::Hash) ||
4626 Parser.getTok().is(AsmToken::Dollar)) {
4627 // Avoid parsing into complex operands (#:)
4628 if (Lexer.peekTok().is(AsmToken::Colon))
4629 return MatchOperand_NoMatch;
4630
4631 // Eat the hash (dollar)
4632 Parser.Lex();
4633 }
4634
4635 SMLoc Sx1, Ex1;
4636 Sx1 = Parser.getTok().getLoc();
4637 const MCExpr *Imm1Exp;
4638 if (getParser().parseExpression(Imm1Exp, Ex1)) {
4639 Error(Sx1, "malformed expression");
4640 return MatchOperand_ParseFail;
4641 }
4642
4643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm1Exp);
4644
4645 if (CE) {
4646 // Immediate must fit within 32-bits
4647 Imm1 = CE->getValue();
4648 int Enc = ARM_AM::getSOImmVal(Imm1);
4649 if (Enc != -1 && Parser.getTok().is(AsmToken::EndOfStatement)) {
4650 // We have a match!
4651 Operands.push_back(ARMOperand::CreateModImm((Enc & 0xFF),
4652 (Enc & 0xF00) >> 7,
4653 Sx1, Ex1));
4654 return MatchOperand_Success;
4655 }
4656
4657 // We have parsed an immediate which is not for us, fallback to a plain
4658 // immediate. This can happen for instruction aliases. For an example,
4659 // ARMInstrInfo.td defines the alias [mov <-> mvn] which can transform
4660 // a mov (mvn) with a mod_imm_neg/mod_imm_not operand into the opposite
4661 // instruction with a mod_imm operand. The alias is defined such that the
4662 // parser method is shared, that's why we have to do this here.
4663 if (Parser.getTok().is(AsmToken::EndOfStatement)) {
4664 Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1));
4665 return MatchOperand_Success;
4666 }
4667 } else {
4668 // Operands like #(l1 - l2) can only be evaluated at a later stage (via an
4669 // MCFixup). Fallback to a plain immediate.
4670 Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1));
4671 return MatchOperand_Success;
4672 }
4673
4674 // From this point onward, we expect the input to be a (#bits, #rot) pair
4675 if (Parser.getTok().isNot(AsmToken::Comma)) {
4676 Error(Sx1, "expected modified immediate operand: #[0, 255], #even[0-30]");
4677 return MatchOperand_ParseFail;
4678 }
4679
4680 if (Imm1 & ~0xFF) {
4681 Error(Sx1, "immediate operand must a number in the range [0, 255]");
4682 return MatchOperand_ParseFail;
4683 }
4684
4685 // Eat the comma
4686 Parser.Lex();
4687
4688 // Repeat for #rot
4689 SMLoc Sx2, Ex2;
4690 Sx2 = Parser.getTok().getLoc();
4691
4692 // Eat the optional hash (dollar)
4693 if (Parser.getTok().is(AsmToken::Hash) ||
4694 Parser.getTok().is(AsmToken::Dollar))
4695 Parser.Lex();
4696
4697 const MCExpr *Imm2Exp;
4698 if (getParser().parseExpression(Imm2Exp, Ex2)) {
4699 Error(Sx2, "malformed expression");
4700 return MatchOperand_ParseFail;
4701 }
4702
4703 CE = dyn_cast<MCConstantExpr>(Imm2Exp);
4704
4705 if (CE) {
4706 Imm2 = CE->getValue();
4707 if (!(Imm2 & ~0x1E)) {
4708 // We have a match!
4709 Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2));
4710 return MatchOperand_Success;
4711 }
4712 Error(Sx2, "immediate operand must an even number in the range [0, 30]");
4713 return MatchOperand_ParseFail;
4714 } else {
4715 Error(Sx2, "constant expression expected");
4716 return MatchOperand_ParseFail;
4717 }
4718}
4719
4720OperandMatchResultTy
4721ARMAsmParser::parseBitfield(OperandVector &Operands) {
4722 MCAsmParser &Parser = getParser();
4723 SMLoc S = Parser.getTok().getLoc();
4724 // The bitfield descriptor is really two operands, the LSB and the width.
4725 if (Parser.getTok().isNot(AsmToken::Hash) &&
4726 Parser.getTok().isNot(AsmToken::Dollar)) {
4727 Error(Parser.getTok().getLoc(), "'#' expected");
4728 return MatchOperand_ParseFail;
4729 }
4730 Parser.Lex(); // Eat hash token.
4731
4732 const MCExpr *LSBExpr;
4733 SMLoc E = Parser.getTok().getLoc();
4734 if (getParser().parseExpression(LSBExpr)) {
4735 Error(E, "malformed immediate expression");
4736 return MatchOperand_ParseFail;
4737 }
4738 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
4739 if (!CE) {
4740 Error(E, "'lsb' operand must be an immediate");
4741 return MatchOperand_ParseFail;
4742 }
4743
4744 int64_t LSB = CE->getValue();
4745 // The LSB must be in the range [0,31]
4746 if (LSB < 0 || LSB > 31) {
4747 Error(E, "'lsb' operand must be in the range [0,31]");
4748 return MatchOperand_ParseFail;
4749 }
4750 E = Parser.getTok().getLoc();
4751
4752 // Expect another immediate operand.
4753 if (Parser.getTok().isNot(AsmToken::Comma)) {
4754 Error(Parser.getTok().getLoc(), "too few operands");
4755 return MatchOperand_ParseFail;
4756 }
4757 Parser.Lex(); // Eat hash token.
4758 if (Parser.getTok().isNot(AsmToken::Hash) &&
4759 Parser.getTok().isNot(AsmToken::Dollar)) {
4760 Error(Parser.getTok().getLoc(), "'#' expected");
4761 return MatchOperand_ParseFail;
4762 }
4763 Parser.Lex(); // Eat hash token.
4764
4765 const MCExpr *WidthExpr;
4766 SMLoc EndLoc;
4767 if (getParser().parseExpression(WidthExpr, EndLoc)) {
4768 Error(E, "malformed immediate expression");
4769 return MatchOperand_ParseFail;
4770 }
4771 CE = dyn_cast<MCConstantExpr>(WidthExpr);
4772 if (!CE) {
4773 Error(E, "'width' operand must be an immediate");
4774 return MatchOperand_ParseFail;
4775 }
4776
4777 int64_t Width = CE->getValue();
4778 // The LSB must be in the range [1,32-lsb]
4779 if (Width < 1 || Width > 32 - LSB) {
4780 Error(E, "'width' operand must be in the range [1,32-lsb]");
4781 return MatchOperand_ParseFail;
4782 }
4783
4784 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc));
4785
4786 return MatchOperand_Success;
4787}
4788
4789OperandMatchResultTy
4790ARMAsmParser::parsePostIdxReg(OperandVector &Operands) {
4791 // Check for a post-index addressing register operand. Specifically:
4792 // postidx_reg := '+' register {, shift}
4793 // | '-' register {, shift}
4794 // | register {, shift}
4795
4796 // This method must return MatchOperand_NoMatch without consuming any tokens
4797 // in the case where there is no match, as other alternatives take other
4798 // parse methods.
4799 MCAsmParser &Parser = getParser();
4800 AsmToken Tok = Parser.getTok();
4801 SMLoc S = Tok.getLoc();
4802 bool haveEaten = false;
4803 bool isAdd = true;
4804 if (Tok.is(AsmToken::Plus)) {
4805 Parser.Lex(); // Eat the '+' token.
4806 haveEaten = true;
4807 } else if (Tok.is(AsmToken::Minus)) {
4808 Parser.Lex(); // Eat the '-' token.
4809 isAdd = false;
4810 haveEaten = true;
4811 }
4812
4813 SMLoc E = Parser.getTok().getEndLoc();
4814 int Reg = tryParseRegister();
4815 if (Reg == -1) {
4816 if (!haveEaten)
4817 return MatchOperand_NoMatch;
4818 Error(Parser.getTok().getLoc(), "register expected");
4819 return MatchOperand_ParseFail;
4820 }
4821
4822 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
4823 unsigned ShiftImm = 0;
4824 if (Parser.getTok().is(AsmToken::Comma)) {
4825 Parser.Lex(); // Eat the ','.
4826 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
4827 return MatchOperand_ParseFail;
4828
4829 // FIXME: Only approximates end...may include intervening whitespace.
4830 E = Parser.getTok().getLoc();
4831 }
4832
4833 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
4834 ShiftImm, S, E));
4835
4836 return MatchOperand_Success;
4837}
4838
4839OperandMatchResultTy
4840ARMAsmParser::parseAM3Offset(OperandVector &Operands) {
4841 // Check for a post-index addressing register operand. Specifically:
4842 // am3offset := '+' register
4843 // | '-' register
4844 // | register
4845 // | # imm
4846 // | # + imm
4847 // | # - imm
4848
4849 // This method must return MatchOperand_NoMatch without consuming any tokens
4850 // in the case where there is no match, as other alternatives take other
4851 // parse methods.
4852 MCAsmParser &Parser = getParser();
4853 AsmToken Tok = Parser.getTok();
4854 SMLoc S = Tok.getLoc();
4855
4856 // Do immediates first, as we always parse those if we have a '#'.
4857 if (Parser.getTok().is(AsmToken::Hash) ||
4858 Parser.getTok().is(AsmToken::Dollar)) {
4859 Parser.Lex(); // Eat '#' or '$'.
4860 // Explicitly look for a '-', as we need to encode negative zero
4861 // differently.
4862 bool isNegative = Parser.getTok().is(AsmToken::Minus);
4863 const MCExpr *Offset;
4864 SMLoc E;
4865 if (getParser().parseExpression(Offset, E))
4866 return MatchOperand_ParseFail;
4867 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4868 if (!CE) {
4869 Error(S, "constant expression expected");
4870 return MatchOperand_ParseFail;
4871 }
4872 // Negative zero is encoded as the flag value
4873 // std::numeric_limits<int32_t>::min().
4874 int32_t Val = CE->getValue();
4875 if (isNegative && Val == 0)
4876 Val = std::numeric_limits<int32_t>::min();
4877
4878 Operands.push_back(
4879 ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, E));
4880
4881 return MatchOperand_Success;
4882 }
4883
4884 bool haveEaten = false;
4885 bool isAdd = true;
4886 if (Tok.is(AsmToken::Plus)) {
4887 Parser.Lex(); // Eat the '+' token.
4888 haveEaten = true;
4889 } else if (Tok.is(AsmToken::Minus)) {
4890 Parser.Lex(); // Eat the '-' token.
4891 isAdd = false;
4892 haveEaten = true;
4893 }
4894
4895 Tok = Parser.getTok();
4896 int Reg = tryParseRegister();
4897 if (Reg == -1) {
4898 if (!haveEaten)
4899 return MatchOperand_NoMatch;
4900 Error(Tok.getLoc(), "register expected");
4901 return MatchOperand_ParseFail;
4902 }
4903
4904 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
4905 0, S, Tok.getEndLoc()));
4906
4907 return MatchOperand_Success;
4908}
4909
4910/// Convert parsed operands to MCInst. Needed here because this instruction
4911/// only has two register operands, but multiplication is commutative so
4912/// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN".
4913void ARMAsmParser::cvtThumbMultiply(MCInst &Inst,
4914 const OperandVector &Operands) {
4915 ((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1);
4916 ((ARMOperand &)*Operands[1]).addCCOutOperands(Inst, 1);
4917 // If we have a three-operand form, make sure to set Rn to be the operand
4918 // that isn't the same as Rd.
4919 unsigned RegOp = 4;
4920 if (Operands.size() == 6 &&
4921 ((ARMOperand &)*Operands[4]).getReg() ==
4922 ((ARMOperand &)*Operands[3]).getReg())
4923 RegOp = 5;
4924 ((ARMOperand &)*Operands[RegOp]).addRegOperands(Inst, 1);
4925 Inst.addOperand(Inst.getOperand(0));
4926 ((ARMOperand &)*Operands[2]).addCondCodeOperands(Inst, 2);
4927}
4928
4929void ARMAsmParser::cvtThumbBranches(MCInst &Inst,
4930 const OperandVector &Operands) {
4931 int CondOp = -1, ImmOp = -1;
4932 switch(Inst.getOpcode()) {
4933 case ARM::tB:
4934 case ARM::tBcc: CondOp = 1; ImmOp = 2; break;
4935
4936 case ARM::t2B:
4937 case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break;
4938
4939 default: llvm_unreachable("Unexpected instruction in cvtThumbBranches")::llvm::llvm_unreachable_internal("Unexpected instruction in cvtThumbBranches"
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 4939)
;
4940 }
4941 // first decide whether or not the branch should be conditional
4942 // by looking at it's location relative to an IT block
4943 if(inITBlock()) {
4944 // inside an IT block we cannot have any conditional branches. any
4945 // such instructions needs to be converted to unconditional form
4946 switch(Inst.getOpcode()) {
4947 case ARM::tBcc: Inst.setOpcode(ARM::tB); break;
4948 case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break;
4949 }
4950 } else {
4951 // outside IT blocks we can only have unconditional branches with AL
4952 // condition code or conditional branches with non-AL condition code
4953 unsigned Cond = static_cast<ARMOperand &>(*Operands[CondOp]).getCondCode();
4954 switch(Inst.getOpcode()) {
4955 case ARM::tB:
4956 case ARM::tBcc:
4957 Inst.setOpcode(Cond == ARMCC::AL ? ARM::tB : ARM::tBcc);
4958 break;
4959 case ARM::t2B:
4960 case ARM::t2Bcc:
4961 Inst.setOpcode(Cond == ARMCC::AL ? ARM::t2B : ARM::t2Bcc);
4962 break;
4963 }
4964 }
4965
4966 // now decide on encoding size based on branch target range
4967 switch(Inst.getOpcode()) {
4968 // classify tB as either t2B or t1B based on range of immediate operand
4969 case ARM::tB: {
4970 ARMOperand &op = static_cast<ARMOperand &>(*Operands[ImmOp]);
4971 if (!op.isSignedOffset<11, 1>() && isThumb() && hasV8MBaseline())
4972 Inst.setOpcode(ARM::t2B);
4973 break;
4974 }
4975 // classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand
4976 case ARM::tBcc: {
4977 ARMOperand &op = static_cast<ARMOperand &>(*Operands[ImmOp]);
4978 if (!op.isSignedOffset<8, 1>() && isThumb() && hasV8MBaseline())
4979 Inst.setOpcode(ARM::t2Bcc);
4980 break;
4981 }
4982 }
4983 ((ARMOperand &)*Operands[ImmOp]).addImmOperands(Inst, 1);
4984 ((ARMOperand &)*Operands[CondOp]).addCondCodeOperands(Inst, 2);
4985}
4986
4987/// Parse an ARM memory expression, return false if successful else return true
4988/// or an error. The first token must be a '[' when called.
4989bool ARMAsmParser::parseMemory(OperandVector &Operands) {
4990 MCAsmParser &Parser = getParser();
4991 SMLoc S, E;
4992 if (Parser.getTok().isNot(AsmToken::LBrac))
4993 return TokError("Token is not a Left Bracket");
4994 S = Parser.getTok().getLoc();
4995 Parser.Lex(); // Eat left bracket token.
4996
4997 const AsmToken &BaseRegTok = Parser.getTok();
4998 int BaseRegNum = tryParseRegister();
4999 if (BaseRegNum == -1)
5000 return Error(BaseRegTok.getLoc(), "register expected");
5001
5002 // The next token must either be a comma, a colon or a closing bracket.
5003 const AsmToken &Tok = Parser.getTok();
5004 if (!Tok.is(AsmToken::Colon) && !Tok.is(AsmToken::Comma) &&
5005 !Tok.is(AsmToken::RBrac))
5006 return Error(Tok.getLoc(), "malformed memory operand");
5007
5008 if (Tok.is(AsmToken::RBrac)) {
5009 E = Tok.getEndLoc();
5010 Parser.Lex(); // Eat right bracket token.
5011
5012 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0,
5013 ARM_AM::no_shift, 0, 0, false,
5014 S, E));
5015
5016 // If there's a pre-indexing writeback marker, '!', just add it as a token
5017 // operand. It's rather odd, but syntactically valid.
5018 if (Parser.getTok().is(AsmToken::Exclaim)) {
5019 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
5020 Parser.Lex(); // Eat the '!'.
5021 }
5022
5023 return false;
5024 }
5025
5026 assert((Tok.is(AsmToken::Colon) || Tok.is(AsmToken::Comma)) &&(static_cast <bool> ((Tok.is(AsmToken::Colon) || Tok.is
(AsmToken::Comma)) && "Lost colon or comma in memory operand?!"
) ? void (0) : __assert_fail ("(Tok.is(AsmToken::Colon) || Tok.is(AsmToken::Comma)) && \"Lost colon or comma in memory operand?!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 5027, __extension__ __PRETTY_FUNCTION__))
5027 "Lost colon or comma in memory operand?!")(static_cast <bool> ((Tok.is(AsmToken::Colon) || Tok.is
(AsmToken::Comma)) && "Lost colon or comma in memory operand?!"
) ? void (0) : __assert_fail ("(Tok.is(AsmToken::Colon) || Tok.is(AsmToken::Comma)) && \"Lost colon or comma in memory operand?!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 5027, __extension__ __PRETTY_FUNCTION__))
;
5028 if (Tok.is(AsmToken::Comma)) {
5029 Parser.Lex(); // Eat the comma.
5030 }
5031
5032 // If we have a ':', it's an alignment specifier.
5033 if (Parser.getTok().is(AsmToken::Colon)) {
5034 Parser.Lex(); // Eat the ':'.
5035 E = Parser.getTok().getLoc();
5036 SMLoc AlignmentLoc = Tok.getLoc();
5037
5038 const MCExpr *Expr;
5039 if (getParser().parseExpression(Expr))
5040 return true;
5041
5042 // The expression has to be a constant. Memory references with relocations
5043 // don't come through here, as they use the <label> forms of the relevant
5044 // instructions.
5045 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
5046 if (!CE)
5047 return Error (E, "constant expression expected");
5048
5049 unsigned Align = 0;
5050 switch (CE->getValue()) {
5051 default:
5052 return Error(E,
5053 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
5054 case 16: Align = 2; break;
5055 case 32: Align = 4; break;
5056 case 64: Align = 8; break;
5057 case 128: Align = 16; break;
5058 case 256: Align = 32; break;
5059 }
5060
5061 // Now we should have the closing ']'
5062 if (Parser.getTok().isNot(AsmToken::RBrac))
5063 return Error(Parser.getTok().getLoc(), "']' expected");
5064 E = Parser.getTok().getEndLoc();
5065 Parser.Lex(); // Eat right bracket token.
5066
5067 // Don't worry about range checking the value here. That's handled by
5068 // the is*() predicates.
5069 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0,
5070 ARM_AM::no_shift, 0, Align,
5071 false, S, E, AlignmentLoc));
5072
5073 // If there's a pre-indexing writeback marker, '!', just add it as a token
5074 // operand.
5075 if (Parser.getTok().is(AsmToken::Exclaim)) {
5076 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
5077 Parser.Lex(); // Eat the '!'.
5078 }
5079
5080 return false;
5081 }
5082
5083 // If we have a '#', it's an immediate offset, else assume it's a register
5084 // offset. Be friendly and also accept a plain integer (without a leading
5085 // hash) for gas compatibility.
5086 if (Parser.getTok().is(AsmToken::Hash) ||
5087 Parser.getTok().is(AsmToken::Dollar) ||
5088 Parser.getTok().is(AsmToken::Integer)) {
5089 if (Parser.getTok().isNot(AsmToken::Integer))
5090 Parser.Lex(); // Eat '#' or '$'.
5091 E = Parser.getTok().getLoc();
5092
5093 bool isNegative = getParser().getTok().is(AsmToken::Minus);
5094 const MCExpr *Offset;
5095 if (getParser().parseExpression(Offset))
5096 return true;
5097
5098 // The expression has to be a constant. Memory references with relocations
5099 // don't come through here, as they use the <label> forms of the relevant
5100 // instructions.
5101 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
5102 if (!CE)
5103 return Error (E, "constant expression expected");
5104
5105 // If the constant was #-0, represent it as
5106 // std::numeric_limits<int32_t>::min().
5107 int32_t Val = CE->getValue();
5108 if (isNegative && Val == 0)
5109 CE = MCConstantExpr::create(std::numeric_limits<int32_t>::min(),
5110 getContext());
5111
5112 // Now we should have the closing ']'
5113 if (Parser.getTok().isNot(AsmToken::RBrac))
5114 return Error(Parser.getTok().getLoc(), "']' expected");
5115 E = Parser.getTok().getEndLoc();
5116 Parser.Lex(); // Eat right bracket token.
5117
5118 // Don't worry about range checking the value here. That's handled by
5119 // the is*() predicates.
5120 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
5121 ARM_AM::no_shift, 0, 0,
5122 false, S, E));
5123
5124 // If there's a pre-indexing writeback marker, '!', just add it as a token
5125 // operand.
5126 if (Parser.getTok().is(AsmToken::Exclaim)) {
5127 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
5128 Parser.Lex(); // Eat the '!'.
5129 }
5130
5131 return false;
5132 }
5133
5134 // The register offset is optionally preceded by a '+' or '-'
5135 bool isNegative = false;
5136 if (Parser.getTok().is(AsmToken::Minus)) {
5137 isNegative = true;
5138 Parser.Lex(); // Eat the '-'.
5139 } else if (Parser.getTok().is(AsmToken::Plus)) {
5140 // Nothing to do.
5141 Parser.Lex(); // Eat the '+'.
5142 }
5143
5144 E = Parser.getTok().getLoc();
5145 int OffsetRegNum = tryParseRegister();
5146 if (OffsetRegNum == -1)
5147 return Error(E, "register expected");
5148
5149 // If there's a shift operator, handle it.
5150 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
5151 unsigned ShiftImm = 0;
5152 if (Parser.getTok().is(AsmToken::Comma)) {
5153 Parser.Lex(); // Eat the ','.
5154 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
5155 return true;
5156 }
5157
5158 // Now we should have the closing ']'
5159 if (Parser.getTok().isNot(AsmToken::RBrac))
5160 return Error(Parser.getTok().getLoc(), "']' expected");
5161 E = Parser.getTok().getEndLoc();
5162 Parser.Lex(); // Eat right bracket token.
5163
5164 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, OffsetRegNum,
5165 ShiftType, ShiftImm, 0, isNegative,
5166 S, E));
5167
5168 // If there's a pre-indexing writeback marker, '!', just add it as a token
5169 // operand.
5170 if (Parser.getTok().is(AsmToken::Exclaim)) {
5171 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
5172 Parser.Lex(); // Eat the '!'.
5173 }
5174
5175 return false;
5176}
5177
5178/// parseMemRegOffsetShift - one of these two:
5179/// ( lsl | lsr | asr | ror ) , # shift_amount
5180/// rrx
5181/// return true if it parses a shift otherwise it returns false.
5182bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
5183 unsigned &Amount) {
5184 MCAsmParser &Parser = getParser();
5185 SMLoc Loc = Parser.getTok().getLoc();
5186 const AsmToken &Tok = Parser.getTok();
5187 if (Tok.isNot(AsmToken::Identifier))
5188 return Error(Loc, "illegal shift operator");
5189 StringRef ShiftName = Tok.getString();
5190 if (ShiftName == "lsl" || ShiftName == "LSL" ||
5191 ShiftName == "asl" || ShiftName == "ASL")
5192 St = ARM_AM::lsl;
5193 else if (ShiftName == "lsr" || ShiftName == "LSR")
5194 St = ARM_AM::lsr;
5195 else if (ShiftName == "asr" || ShiftName == "ASR")
5196 St = ARM_AM::asr;
5197 else if (ShiftName == "ror" || ShiftName == "ROR")
5198 St = ARM_AM::ror;
5199 else if (ShiftName == "rrx" || ShiftName == "RRX")
5200 St = ARM_AM::rrx;
5201 else
5202 return Error(Loc, "illegal shift operator");
5203 Parser.Lex(); // Eat shift type token.
5204
5205 // rrx stands alone.
5206 Amount = 0;
5207 if (St != ARM_AM::rrx) {
5208 Loc = Parser.getTok().getLoc();
5209 // A '#' and a shift amount.
5210 const AsmToken &HashTok = Parser.getTok();
5211 if (HashTok.isNot(AsmToken::Hash) &&
5212 HashTok.isNot(AsmToken::Dollar))
5213 return Error(HashTok.getLoc(), "'#' expected");
5214 Parser.Lex(); // Eat hash token.
5215
5216 const MCExpr *Expr;
5217 if (getParser().parseExpression(Expr))
5218 return true;
5219 // Range check the immediate.
5220 // lsl, ror: 0 <= imm <= 31
5221 // lsr, asr: 0 <= imm <= 32
5222 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
5223 if (!CE)
5224 return Error(Loc, "shift amount must be an immediate");
5225 int64_t Imm = CE->getValue();
5226 if (Imm < 0 ||
5227 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
5228 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
5229 return Error(Loc, "immediate shift value out of range");
5230 // If <ShiftTy> #0, turn it into a no_shift.
5231 if (Imm == 0)
5232 St = ARM_AM::lsl;
5233 // For consistency, treat lsr #32 and asr #32 as having immediate value 0.
5234 if (Imm == 32)
5235 Imm = 0;
5236 Amount = Imm;
5237 }
5238
5239 return false;
5240}
5241
5242/// parseFPImm - A floating point immediate expression operand.
5243OperandMatchResultTy
5244ARMAsmParser::parseFPImm(OperandVector &Operands) {
5245 MCAsmParser &Parser = getParser();
5246 // Anything that can accept a floating point constant as an operand
5247 // needs to go through here, as the regular parseExpression is
5248 // integer only.
5249 //
5250 // This routine still creates a generic Immediate operand, containing
5251 // a bitcast of the 64-bit floating point value. The various operands
5252 // that accept floats can check whether the value is valid for them
5253 // via the standard is*() predicates.
5254
5255 SMLoc S = Parser.getTok().getLoc();
5256
5257 if (Parser.getTok().isNot(AsmToken::Hash) &&
5258 Parser.getTok().isNot(AsmToken::Dollar))
5259 return MatchOperand_NoMatch;
5260
5261 // Disambiguate the VMOV forms that can accept an FP immediate.
5262 // vmov.f32 <sreg>, #imm
5263 // vmov.f64 <dreg>, #imm
5264 // vmov.f32 <dreg>, #imm @ vector f32x2
5265 // vmov.f32 <qreg>, #imm @ vector f32x4
5266 //
5267 // There are also the NEON VMOV instructions which expect an
5268 // integer constant. Make sure we don't try to parse an FPImm
5269 // for these:
5270 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
5271 ARMOperand &TyOp = static_cast<ARMOperand &>(*Operands[2]);
5272 bool isVmovf = TyOp.isToken() &&
5273 (TyOp.getToken() == ".f32" || TyOp.getToken() == ".f64" ||
5274 TyOp.getToken() == ".f16");
5275 ARMOperand &Mnemonic = static_cast<ARMOperand &>(*Operands[0]);
5276 bool isFconst = Mnemonic.isToken() && (Mnemonic.getToken() == "fconstd" ||
5277 Mnemonic.getToken() == "fconsts");
5278 if (!(isVmovf || isFconst))
5279 return MatchOperand_NoMatch;
5280
5281 Parser.Lex(); // Eat '#' or '$'.
5282
5283 // Handle negation, as that still comes through as a separate token.
5284 bool isNegative = false;
5285 if (Parser.getTok().is(AsmToken::Minus)) {
5286 isNegative = true;
5287 Parser.Lex();
5288 }
5289 const AsmToken &Tok = Parser.getTok();
5290 SMLoc Loc = Tok.getLoc();
5291 if (Tok.is(AsmToken::Real) && isVmovf) {
5292 APFloat RealVal(APFloat::IEEEsingle(), Tok.getString());
5293 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
5294 // If we had a '-' in front, toggle the sign bit.
5295 IntVal ^= (uint64_t)isNegative << 31;
5296 Parser.Lex(); // Eat the token.
5297 Operands.push_back(ARMOperand::CreateImm(
5298 MCConstantExpr::create(IntVal, getContext()),
5299 S, Parser.getTok().getLoc()));
5300 return MatchOperand_Success;
5301 }
5302 // Also handle plain integers. Instructions which allow floating point
5303 // immediates also allow a raw encoded 8-bit value.
5304 if (Tok.is(AsmToken::Integer) && isFconst) {
5305 int64_t Val = Tok.getIntVal();
5306 Parser.Lex(); // Eat the token.
5307 if (Val > 255 || Val < 0) {
5308 Error(Loc, "encoded floating point value out of range");
5309 return MatchOperand_ParseFail;
5310 }
5311 float RealVal = ARM_AM::getFPImmFloat(Val);
5312 Val = APFloat(RealVal).bitcastToAPInt().getZExtValue();
5313
5314 Operands.push_back(ARMOperand::CreateImm(
5315 MCConstantExpr::create(Val, getContext()), S,
5316 Parser.getTok().getLoc()));
5317 return MatchOperand_Success;
5318 }
5319
5320 Error(Loc, "invalid floating point immediate");
5321 return MatchOperand_ParseFail;
5322}
5323
5324/// Parse a arm instruction operand. For now this parses the operand regardless
5325/// of the mnemonic.
5326bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
5327 MCAsmParser &Parser = getParser();
5328 SMLoc S, E;
5329
5330 // Check if the current operand has a custom associated parser, if so, try to
5331 // custom parse the operand, or fallback to the general approach.
5332 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5333 if (ResTy == MatchOperand_Success)
5334 return false;
5335 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5336 // there was a match, but an error occurred, in which case, just return that
5337 // the operand parsing failed.
5338 if (ResTy == MatchOperand_ParseFail)
5339 return true;
5340
5341 switch (getLexer().getKind()) {
5342 default:
5343 Error(Parser.getTok().getLoc(), "unexpected token in operand");
5344 return true;
5345 case AsmToken::Identifier: {
5346 // If we've seen a branch mnemonic, the next operand must be a label. This
5347 // is true even if the label is a register name. So "br r1" means branch to
5348 // label "r1".
5349 bool ExpectLabel = Mnemonic == "b" || Mnemonic == "bl";
5350 if (!ExpectLabel) {
5351 if (!tryParseRegisterWithWriteBack(Operands))
5352 return false;
5353 int Res = tryParseShiftRegister(Operands);
5354 if (Res == 0) // success
5355 return false;
5356 else if (Res == -1) // irrecoverable error
5357 return true;
5358 // If this is VMRS, check for the apsr_nzcv operand.
5359 if (Mnemonic == "vmrs" &&
5360 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
5361 S = Parser.getTok().getLoc();
5362 Parser.Lex();
5363 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
5364 return false;
5365 }
5366 }
5367
5368 // Fall though for the Identifier case that is not a register or a
5369 // special name.
5370 LLVM_FALLTHROUGH[[clang::fallthrough]];
5371 }
5372 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
5373 case AsmToken::Integer: // things like 1f and 2b as a branch targets
5374 case AsmToken::String: // quoted label names.
5375 case AsmToken::Dot: { // . as a branch target
5376 // This was not a register so parse other operands that start with an
5377 // identifier (like labels) as expressions and create them as immediates.
5378 const MCExpr *IdVal;
5379 S = Parser.getTok().getLoc();
5380 if (getParser().parseExpression(IdVal))
5381 return true;
5382 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5383 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
5384 return false;
5385 }
5386 case AsmToken::LBrac:
5387 return parseMemory(Operands);
5388 case AsmToken::LCurly:
5389 return parseRegisterList(Operands);
5390 case AsmToken::Dollar:
5391 case AsmToken::Hash:
5392 // #42 -> immediate.
5393 S = Parser.getTok().getLoc();
5394 Parser.Lex();
5395
5396 if (Parser.getTok().isNot(AsmToken::Colon)) {
5397 bool isNegative = Parser.getTok().is(AsmToken::Minus);
5398 const MCExpr *ImmVal;
5399 if (getParser().parseExpression(ImmVal))
5400 return true;
5401 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
5402 if (CE) {
5403 int32_t Val = CE->getValue();
5404 if (isNegative && Val == 0)
5405 ImmVal = MCConstantExpr::create(std::numeric_limits<int32_t>::min(),
5406 getContext());
5407 }
5408 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5409 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
5410
5411 // There can be a trailing '!' on operands that we want as a separate
5412 // '!' Token operand. Handle that here. For example, the compatibility
5413 // alias for 'srsdb sp!, #imm' is 'srsdb #imm!'.
5414 if (Parser.getTok().is(AsmToken::Exclaim)) {
5415 Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(),
5416 Parser.getTok().getLoc()));
5417 Parser.Lex(); // Eat exclaim token
5418 }
5419 return false;
5420 }
5421 // w/ a ':' after the '#', it's just like a plain ':'.
5422 LLVM_FALLTHROUGH[[clang::fallthrough]];
5423
5424 case AsmToken::Colon: {
5425 S = Parser.getTok().getLoc();
5426 // ":lower16:" and ":upper16:" expression prefixes
5427 // FIXME: Check it's an expression prefix,
5428 // e.g. (FOO - :lower16:BAR) isn't legal.
5429 ARMMCExpr::VariantKind RefKind;
5430 if (parsePrefix(RefKind))
5431 return true;
5432
5433 const MCExpr *SubExprVal;
5434 if (getParser().parseExpression(SubExprVal))
5435 return true;
5436
5437 const MCExpr *ExprVal = ARMMCExpr::create(RefKind, SubExprVal,
5438 getContext());
5439 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5440 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
5441 return false;
5442 }
5443 case AsmToken::Equal: {
5444 S = Parser.getTok().getLoc();
5445 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
5446 return Error(S, "unexpected token in operand");
5447 Parser.Lex(); // Eat '='
5448 const MCExpr *SubExprVal;
5449 if (getParser().parseExpression(SubExprVal))
5450 return true;
5451 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5452
5453 // execute-only: we assume that assembly programmers know what they are
5454 // doing and allow literal pool creation here
5455 Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E));
5456 return false;
5457 }
5458 }
5459}
5460
5461// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
5462// :lower16: and :upper16:.
5463bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
5464 MCAsmParser &Parser = getParser();
5465 RefKind = ARMMCExpr::VK_ARM_None;
5466
5467 // consume an optional '#' (GNU compatibility)
5468 if (getLexer().is(AsmToken::Hash))
5469 Parser.Lex();
5470
5471 // :lower16: and :upper16: modifiers
5472 assert(getLexer().is(AsmToken::Colon) && "expected a :")(static_cast <bool> (getLexer().is(AsmToken::Colon) &&
"expected a :") ? void (0) : __assert_fail ("getLexer().is(AsmToken::Colon) && \"expected a :\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/ARM/AsmParser/ARMAsmParser.cpp"
, 5472, __extension__ __PRETTY_FUNCTION__))
;
5473 Parser.Lex(); // Eat ':'
5474
5475 if (getLexer().isNot(AsmToken::Identifier)) {
5476 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
5477 return true;
5478 }
5479
5480 enum {
5481 COFF = (1 << MCObjectFileInfo::IsCOFF),
5482 ELF = (1 << MCObjectFileInfo::IsELF),
5483 MACHO = (1 << MCObjectFileInfo::IsMachO),
5484 WASM = (1 << MCObjectFileInfo::IsWasm),
5485 };
5486 static const struct PrefixEntry {
5487 const char *Spelling;
5488 ARMMCExpr::VariantKind VariantKind;
5489 uint8_t SupportedFormats;
5490 } PrefixEntries[] = {
5491 { "lower16", ARMMCExpr::VK_ARM_LO16, COFF | ELF | MACHO },
5492 { "upper16", ARMMCExpr::VK_ARM_HI16, COFF | ELF | MACHO },
5493 };
5494
5495 StringRef IDVal = Parser.getTok().getIdentifier();
5496
5497 const auto &Prefix =
5498 std::find_if(std::begin(PrefixEntries), std::end(PrefixEntries),
5499 [&IDVal](const PrefixEntry &PE) {
5500 return PE.Spelling == IDVal;
5501 });
5502 if (Prefix == std::end(PrefixEntries)) {
5503 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
5504 return true;
5505 }
5506
5507 uint8_t CurrentFormat;
5508 switch (getContext().getObjectFileInfo()->getObjectFileType()) {
5509 case MCObjectFileInfo::IsMachO:
5510 CurrentFormat = MACHO;
5511 break;
5512 case MCObjectFileInfo::IsELF:
5513 CurrentFormat = ELF;
5514 break;
5515 case MCObjectFileInfo::IsCOFF:
5516 CurrentFormat = COFF;
5517 break;
5518 case MCObjectFileInfo::IsWasm:
5519 CurrentFormat = WASM;
5520 break;
5521 }
5522
5523 if (~Prefix->SupportedFormats & CurrentFormat) {
5524 Error(Parser.getTok().getLoc(),
5525 "cannot represent relocation in the current file format");
5526 return true;
5527 }
5528
5529 RefKind = Prefix->VariantKind;
5530 Parser.Lex();
5531
5532 if (getLexer().isNot(AsmToken::Colon)) {
5533 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
5534 return true;
5535 }
5536 Parser.Lex(); // Eat the last ':'
5537
5538 return false;
5539}
5540
5541/// \brief Given a mnemonic, split out possible predication code and carry
5542/// setting letters to form a canonical mnemonic and flags.
5543//
5544// FIXME: Would be nice to autogen this.
5545// FIXME: This is a bit of a maze of special cases.
5546StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
5547 unsigned &PredicationCode,
5548 bool &CarrySetting,
5549 unsigned &ProcessorIMod,
5550 StringRef &ITMask) {
5551 PredicationCode = ARMCC::AL;
5552 CarrySetting = false;
5553 ProcessorIMod = 0;
5554
5555 // Ignore some mnemonics we know aren't predicated forms.
5556 //
5557 // FIXME: Would be nice to autogen this.
5558 if ((Mnemonic == "movs" && isThumb()) ||
5559 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
5560 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
5561 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
5562 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
5563 Mnemonic == "vaclt" || Mnemonic == "vacle" || Mnemonic == "hlt" ||
5564 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
5565 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
5566 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
5567 Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" ||
5568 Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" ||
5569 Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" ||
5570 Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" ||
5571 Mnemonic.startswith("vsel") || Mnemonic == "vins" || Mnemonic == "vmovx" ||
5572 Mnemonic == "bxns" || Mnemonic == "blxns" ||
5573 Mnemonic == "vudot" || Mnemonic == "vsdot" ||
5574 Mnemonic == "vcmla" || Mnemonic == "vcadd")
5575 return Mnemonic;
5576
5577 // First, split out any predication code. Ignore mnemonics we know aren't
5578 // predicated but do have a carry-set and so weren't caught above.
5579 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
5580 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
5581 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
5582 Mnemonic != "sbcs" && Mnemonic != "rscs") {
5583 unsigned CC = ARMCondCodeFromString(Mnemonic.substr(Mnemonic.size()-2));
5584 if (CC != ~0U) {
5585 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
5586 PredicationCode = CC;
5587 }
5588 }
5589
5590 // Next, determine if we have a carry setting bit. We explicitly ignore all
5591 // the instructions we know end in 's'.
5592 if (Mnemonic.endswith("s") &&
5593 !(Mnemonic == "cps" || Mnemonic == "mls" ||
5594 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
5595 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
5596 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
5597 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
5598 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
5599 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
5600 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
5601 Mnemonic == "vfms" || Mnemonic == "vfnms" || Mnemonic == "fconsts" ||
5602 Mnemonic == "bxns" || Mnemonic == "blxns" ||
5603 (Mnemonic == "movs" && isThumb()))) {
5604 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
5605 CarrySetting = true;
5606 }
5607
5608 // The "cps" instruction can have a interrupt mode operand which is glued into
5609 // the mnemonic. Check if this is the case, split it and parse the imod op
5610 if (Mnemonic.startswith("cps")) {
5611 // Split out any imod code.
5612 unsigned IMod =
5613 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
5614 .Case("ie", ARM_PROC::IE)
5615 .Case("id", ARM_PROC::ID)
5616 .Default(~0U);
5617 if (IMod != ~0U) {
5618 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
5619 ProcessorIMod = IMod;
5620 }
5621 }
5622
5623 // The "it" instruction has the condition mask on the end of the mnemonic.
5624 if (Mnemonic.startswith("it")) {
5625 ITMask = Mnemonic.slice(2, Mnemonic.size());
5626 Mnemonic = Mnemonic.slice(0, 2);
5627 }
5628
5629 return Mnemonic;
5630}
5631
5632/// \brief Given a canonical mnemonic, determine if the instruction ever allows
5633/// inclusion of carry set or predication code operands.
5634//
5635// FIXME: It would be nice to autogen this.
5636void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst,
5637 bool &CanAcceptCarrySet,
5638 bool &CanAcceptPredicationCode) {
5639 CanAcceptCarrySet =
5640 Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
5641 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
5642 Mnemonic == "add" || Mnemonic == "adc" || Mnemonic == "mul" ||
5643 Mnemonic == "bic" || Mnemonic == "asr" || Mnemonic == "orr" ||
5644 Mnemonic == "mvn" || Mnemonic == "rsb" || Mnemonic == "rsc" ||
5645 Mnemonic == "orn" || Mnemonic == "sbc" || Mnemonic == "eor" ||
5646 Mnemonic == "neg" || Mnemonic == "vfm" || Mnemonic == "vfnm" ||
5647 (!isThumb() &&
5648 (Mnemonic == "smull" || Mnemonic == "mov" || Mnemonic == "mla" ||
5649 Mnemonic == "smlal" || Mnemonic == "umlal" || Mnemonic == "umull"));
5650
5651 if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" ||
5652 Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" ||
5653 Mnemonic == "trap" || Mnemonic == "hlt" || Mnemonic == "udf" ||
5654 Mnemonic.startswith("crc32") || Mnemonic.startswith("cps") ||
5655 Mnemonic.startswith("vsel") || Mnemonic == "vmaxnm" ||
5656 Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" ||
5657 Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" ||
5658 Mnemonic == "vrintn" || Mnemonic == "vrintp" || Mnemonic == "vrintm" ||
5659 Mnemonic.startswith("aes") || Mnemonic == "hvc" || Mnemonic == "setpan" ||
5660 Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") ||
5661 (FullInst.startswith("vmull") && FullInst.endswith(".p64")) ||
5662 Mnemonic == "vmovx" || Mnemonic == "vins" ||
5663 Mnemonic == "vudot" || Mnemonic == "vsdot" ||
5664 Mnemonic == "vcmla" || Mnemonic == "vcadd") {
5665 // These mnemonics are never predicable
5666 CanAcceptPredicationCode = false;
5667 } else if (!isThumb()) {
5668 // Some instructions are only predicable in Thumb mode
5669 CanAcceptPredicationCode =
5670 Mnemonic != "cdp2" && Mnemonic != "clrex" && Mnemonic != "mcr2" &&
5671 Mnemonic != "mcrr2" && Mnemonic != "mrc2" && Mnemonic != "mrrc2" &&
5672 Mnemonic != "dmb" && Mnemonic != "dfb" && Mnemonic != "dsb" &&
5673 Mnemonic != "isb" && Mnemonic != "pld" && Mnemonic != "pli" &&
5674 Mnemonic != "pldw" && Mnemonic != "ldc2" && Mnemonic != "ldc2l" &&
5675 Mnemonic != "stc2" && Mnemonic != "stc2l" &&
5676 !Mnemonic.startswith("rfe") && !Mnemonic.startswith("srs");
5677 } else if (isThumbOne()) {
5678 if (hasV6MOps())
5679 CanAcceptPredicationCode = Mnemonic != "movs";
5680 else
5681 CanAcceptPredicationCode = Mnemonic != "nop" && Mnemonic != "movs";
5682 } else
5683 CanAcceptPredicationCode = true;
5684}
5685
5686// \brief Some Thumb instructions have two operand forms that are not
5687// available as three operand, convert to two operand form if possible.
5688//
5689// FIXME: We would really like to be able to tablegen'erate this.
5690void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic,
5691 bool CarrySetting,
5692 OperandVector &Operands) {
5693 if (Operands.size() != 6)
5694 return;
5695
5696 const auto &Op3 = static_cast<ARMOperand &>(*Operands[3]);
5697 auto &Op4 = static_cast<ARMOperand &>(*Operands[4]);
5698 if (!Op3.isReg() || !Op4.isReg())
5699 return;
5700
5701 auto Op3Reg = Op3.getReg();
5702 auto Op4Reg = Op4.getReg();
5703
5704 // For most Thumb2 cases we just generate the 3 operand form and reduce
5705 // it in processInstruction(), but the 3 operand form of ADD (t2ADDrr)
5706 // won't accept SP or PC so we do the transformation here taking care
5707 // with immediate range in the 'add sp, sp #imm' case.
5708 auto &Op5 = static_cast<ARMOperand &>(*Operands[5]);
5709 if (isThumbTwo()) {
5710 if (Mnemonic != "add")
5711 return;
5712 bool TryTransform = Op3Reg == ARM::PC || Op4Reg == ARM::PC ||
5713 (Op5.isReg() && Op5.getReg() == ARM::PC);
5714 if (!TryTransform) {
5715 TryTransform = (Op3Reg == ARM::SP || Op4Reg == ARM::SP ||
5716 (Op5.isReg() && Op5.getReg() == ARM::SP)) &&
5717 !(Op3Reg == ARM::SP && Op4Reg == ARM::SP &&
5718 Op5.isImm() && !Op5.isImm0_508s4());
5719 }
5720 if (!TryTransform)
5721 return;
5722 } else if (!isThumbOne())
5723 return;
5724
5725 if (!(Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" ||
5726 Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
5727 Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" ||
5728 Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic"))
5729 return;