Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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