Bug Summary

File:lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Warning:line 337, 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-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-8/lib/clang/8.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/lib/Target/ARM/AsmParser -I /build/llvm-toolchain-snapshot-8~svn345461/lib/Target/ARM/AsmParser -I /build/llvm-toolchain-snapshot-8~svn345461/lib/Target/ARM -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/lib/Target/ARM -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/include -I /build/llvm-toolchain-snapshot-8~svn345461/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/8.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-8/lib/clang/8.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-8~svn345461/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-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-10-27-211344-32123-1 -x c++ /build/llvm-toolchain-snapshot-8~svn345461/lib/Target/ARM/AsmParser/ARMAsmParser.cpp -faddrsig

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