blob: 7822501e7eca8bd319ec3f4e03d365410e8bcc0a [file] [log] [blame]
Kevin Enderbyccab3172009-09-15 00:27:25 +00001//===-- 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
Evan Cheng11424442011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chenga20cde32011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindolae90c1cb2011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbachc6db8ce2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyccab3172009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng4d6c9d72011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng11424442011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng11424442011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach3d1eac82011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng2bb40352011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbar4a863e62010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach5c932b22011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramerdebe69f2011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng11424442011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar188b47b2010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000035
Kevin Enderbyccab3172009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +000038namespace {
Bill Wendlingee7f1f92010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach624bcc72010-10-29 14:46:02 +000041
Jim Grosbach04945c42011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbachcd6f5e72011-11-30 01:09:44 +000043
Evan Cheng11424442011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000046 MCAsmParser &Parser;
Jim Grosbachc988e0c2012-03-05 19:33:30 +000047 const MCRegisterInfo *MRI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000048
Jim Grosbachab5830e2011-12-14 02:16:11 +000049 // Map of register aliases registers via the .req directive.
50 StringMap<unsigned> RegisterReqs;
51
Jim Grosbached16ec42011-08-29 22:24:09 +000052 struct {
53 ARMCC::CondCodes Cond; // Condition for IT block.
54 unsigned Mask:4; // Condition mask for instructions.
55 // Starting at first 1 (from lsb).
56 // '1' condition as indicated in IT.
57 // '0' inverse of condition (else).
58 // Count of instructions in IT block is
59 // 4 - trailingzeroes(mask)
60
61 bool FirstCond; // Explicit flag for when we're parsing the
62 // First instruction in the IT block. It's
63 // implied in the mask, so needs special
64 // handling.
65
66 unsigned CurPosition; // Current position in parsing of IT
67 // block. In range [0,3]. Initialized
68 // according to count of instructions in block.
69 // ~0U if no active IT block.
70 } ITState;
71 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000072 void forwardITPosition() {
73 if (!inITBlock()) return;
74 // Move to the next instruction in the IT block, if there is one. If not,
75 // mark the block as done.
76 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
77 if (++ITState.CurPosition == 5 - TZ)
78 ITState.CurPosition = ~0U; // Done with the IT block after this.
79 }
Jim Grosbached16ec42011-08-29 22:24:09 +000080
81
Kevin Enderbyccab3172009-09-15 00:27:25 +000082 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000083 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
84
Benjamin Kramer673824b2012-04-15 17:04:27 +000085 bool Warning(SMLoc L, const Twine &Msg,
86 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
87 return Parser.Warning(L, Msg, Ranges);
88 }
89 bool Error(SMLoc L, const Twine &Msg,
90 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
91 return Parser.Error(L, Msg, Ranges);
92 }
Kevin Enderbyccab3172009-09-15 00:27:25 +000093
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000094 int tryParseRegister();
95 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000096 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000097 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000098 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000099 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
100 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +0000101 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
102 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000103 bool parseDirectiveWord(unsigned Size, SMLoc L);
104 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach7f882392011-12-07 18:04:19 +0000105 bool parseDirectiveARM(SMLoc L);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000106 bool parseDirectiveThumbFunc(SMLoc L);
107 bool parseDirectiveCode(SMLoc L);
108 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbachab5830e2011-12-14 02:16:11 +0000109 bool parseDirectiveReq(StringRef Name, SMLoc L);
110 bool parseDirectiveUnreq(SMLoc L);
Jason W Kim135d2442011-12-20 17:38:12 +0000111 bool parseDirectiveArch(SMLoc L);
112 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +0000113
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000114 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000115 bool &CarrySetting, unsigned &ProcessorIMod,
116 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000117 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000118 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000119
Evan Cheng4d1ca962011-07-08 01:53:10 +0000120 bool isThumb() const {
121 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000122 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000123 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000124 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000125 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000126 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000127 bool isThumbTwo() const {
128 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
129 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000130 bool hasV6Ops() const {
131 return STI.getFeatureBits() & ARM::HasV6Ops;
132 }
James Molloy21efa7d2011-09-28 14:21:38 +0000133 bool hasV7Ops() const {
134 return STI.getFeatureBits() & ARM::HasV7Ops;
135 }
Evan Cheng284b4672011-07-08 22:36:29 +0000136 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000137 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
138 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000139 }
James Molloy21efa7d2011-09-28 14:21:38 +0000140 bool isMClass() const {
141 return STI.getFeatureBits() & ARM::FeatureMClass;
142 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000143
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000144 /// @name Auto-generated Match Functions
145 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000146
Chris Lattner3e4582a2010-09-06 19:11:01 +0000147#define GET_ASSEMBLER_HEADER
148#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000149
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000150 /// }
151
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000152 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000153 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000154 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000155 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000156 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000157 OperandMatchResultTy parseCoprocOptionOperand(
158 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000159 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000160 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000161 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000162 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000163 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000164 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000165 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
166 StringRef Op, int Low, int High);
167 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
168 return parsePKHImm(O, "lsl", 0, 31);
169 }
170 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
171 return parsePKHImm(O, "asr", 1, 32);
172 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000173 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000174 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000175 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000176 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000177 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000178 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000179 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000180 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach04945c42011-12-02 00:35:16 +0000181 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000182
183 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000184 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000188 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000190 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000192 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000194 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000196 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000198 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000200 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000202 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
204 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
208 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000210 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000212 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
213 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000214 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
215 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000216 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
217 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach3ea06572011-10-24 22:16:58 +0000218 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
219 const SmallVectorImpl<MCParsedAsmOperand*> &);
220 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
221 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach05df4602011-10-31 21:50:31 +0000222 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
223 const SmallVectorImpl<MCParsedAsmOperand*> &);
224 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
225 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000226
227 bool validateInstruction(MCInst &Inst,
228 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachafad0532011-11-10 23:42:14 +0000229 bool processInstruction(MCInst &Inst,
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000230 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000231 bool shouldOmitCCOutOperand(StringRef Mnemonic,
232 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000233
Kevin Enderbyccab3172009-09-15 00:27:25 +0000234public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000235 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000236 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000237 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000238 Match_RequiresV6,
239 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000240 };
241
Evan Cheng91111d22011-07-09 05:47:46 +0000242 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000243 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000244 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000245
Jim Grosbachc988e0c2012-03-05 19:33:30 +0000246 // Cache the MCRegisterInfo.
247 MRI = &getContext().getRegisterInfo();
248
Evan Cheng4d1ca962011-07-08 01:53:10 +0000249 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000250 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000251
252 // Not in an ITBlock to start with.
253 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000254 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000255
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000256 // Implementation of the MCTargetAsmParser interface:
257 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
258 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000259 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000260 bool ParseDirective(AsmToken DirectiveID);
261
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000262 unsigned checkTargetMatchPredicate(MCInst &Inst);
263
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000264 bool MatchAndEmitInstruction(SMLoc IDLoc,
265 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
266 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000267};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000268} // end anonymous namespace
269
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000270namespace {
271
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000272/// ARMOperand - Instances of this class represent a parsed ARM machine
273/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000274class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000275 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000276 k_CondCode,
277 k_CCOut,
278 k_ITCondMask,
279 k_CoprocNum,
280 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000281 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000282 k_Immediate,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000283 k_MemBarrierOpt,
284 k_Memory,
285 k_PostIndexRegister,
286 k_MSRMask,
287 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000288 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000289 k_Register,
290 k_RegisterList,
291 k_DPRRegisterList,
292 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000293 k_VectorList,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000294 k_VectorListAllLanes,
Jim Grosbach04945c42011-12-02 00:35:16 +0000295 k_VectorListIndexed,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000296 k_ShiftedRegister,
297 k_ShiftedImmediate,
298 k_ShifterImmediate,
299 k_RotateImmediate,
300 k_BitfieldDescriptor,
301 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000302 } Kind;
303
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000304 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000305 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000306
307 union {
308 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000309 ARMCC::CondCodes Val;
310 } CC;
311
312 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000313 unsigned Val;
314 } Cop;
315
316 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000317 unsigned Val;
318 } CoprocOption;
319
320 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000321 unsigned Mask:4;
322 } ITMask;
323
324 struct {
325 ARM_MB::MemBOpt Val;
326 } MBOpt;
327
328 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000329 ARM_PROC::IFlags Val;
330 } IFlags;
331
332 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000333 unsigned Val;
334 } MMask;
335
336 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000337 const char *Data;
338 unsigned Length;
339 } Tok;
340
341 struct {
342 unsigned RegNum;
343 } Reg;
344
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000345 // A vector register list is a sequential list of 1 to 4 registers.
346 struct {
347 unsigned RegNum;
348 unsigned Count;
Jim Grosbach04945c42011-12-02 00:35:16 +0000349 unsigned LaneIndex;
Jim Grosbach2f50e922011-12-15 21:44:33 +0000350 bool isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000351 } VectorList;
352
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000353 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000354 unsigned Val;
355 } VectorIndex;
356
357 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000358 const MCExpr *Val;
359 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000360
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000361 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000362 struct {
363 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000364 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
365 // was specified.
366 const MCConstantExpr *OffsetImm; // Offset immediate value
367 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
368 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000369 unsigned ShiftImm; // shift for OffsetReg.
370 unsigned Alignment; // 0 = no alignment specified
Jim Grosbachcef98cd2011-12-19 18:31:43 +0000371 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000372 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000373 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000374
375 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000376 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000377 bool isAdd;
378 ARM_AM::ShiftOpc ShiftTy;
379 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000380 } PostIdxReg;
381
382 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000383 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000384 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000385 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000386 struct {
387 ARM_AM::ShiftOpc ShiftTy;
388 unsigned SrcReg;
389 unsigned ShiftReg;
390 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000391 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000392 struct {
393 ARM_AM::ShiftOpc ShiftTy;
394 unsigned SrcReg;
395 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000396 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000397 struct {
398 unsigned Imm;
399 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000400 struct {
401 unsigned LSB;
402 unsigned Width;
403 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000404 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000405
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000406 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
407public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000408 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
409 Kind = o.Kind;
410 StartLoc = o.StartLoc;
411 EndLoc = o.EndLoc;
412 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000413 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000414 CC = o.CC;
415 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000416 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000417 ITMask = o.ITMask;
418 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000419 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000420 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000421 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000422 case k_CCOut:
423 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000424 Reg = o.Reg;
425 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000426 case k_RegisterList:
427 case k_DPRRegisterList:
428 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000429 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000430 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000431 case k_VectorList:
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000432 case k_VectorListAllLanes:
Jim Grosbach04945c42011-12-02 00:35:16 +0000433 case k_VectorListIndexed:
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000434 VectorList = o.VectorList;
435 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000436 case k_CoprocNum:
437 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000438 Cop = o.Cop;
439 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000440 case k_CoprocOption:
441 CoprocOption = o.CoprocOption;
442 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000443 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000444 Imm = o.Imm;
445 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000446 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000447 MBOpt = o.MBOpt;
448 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000449 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000450 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000451 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000452 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000453 PostIdxReg = o.PostIdxReg;
454 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000455 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000456 MMask = o.MMask;
457 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000458 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000459 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000460 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000461 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000462 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000463 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000464 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000465 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000466 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000467 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000468 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000469 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000470 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000471 RotImm = o.RotImm;
472 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000473 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000474 Bitfield = o.Bitfield;
475 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000476 case k_VectorIndex:
477 VectorIndex = o.VectorIndex;
478 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000479 }
480 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000481
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000482 /// getStartLoc - Get the location of the first token of this operand.
483 SMLoc getStartLoc() const { return StartLoc; }
484 /// getEndLoc - Get the location of the last token of this operand.
485 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000486
Benjamin Kramer673824b2012-04-15 17:04:27 +0000487 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
488
Daniel Dunbard8042b72010-08-11 06:36:53 +0000489 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000490 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000491 return CC.Val;
492 }
493
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000494 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000495 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000496 return Cop.Val;
497 }
498
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000499 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000500 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000501 return StringRef(Tok.Data, Tok.Length);
502 }
503
504 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000505 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000506 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000507 }
508
Bill Wendlingbed94652010-11-09 23:28:44 +0000509 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000510 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
511 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000512 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000513 }
514
Kevin Enderbyf5079942009-10-13 22:19:02 +0000515 const MCExpr *getImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000516 assert(isImm() && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000517 return Imm.Val;
518 }
519
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000520 unsigned getVectorIndex() const {
521 assert(Kind == k_VectorIndex && "Invalid access!");
522 return VectorIndex.Val;
523 }
524
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000525 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000526 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000527 return MBOpt.Val;
528 }
529
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000530 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000531 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000532 return IFlags.Val;
533 }
534
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000535 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000536 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000537 return MMask.Val;
538 }
539
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000540 bool isCoprocNum() const { return Kind == k_CoprocNum; }
541 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000542 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000543 bool isCondCode() const { return Kind == k_CondCode; }
544 bool isCCOut() const { return Kind == k_CCOut; }
545 bool isITMask() const { return Kind == k_ITCondMask; }
546 bool isITCondCode() const { return Kind == k_CondCode; }
547 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +0000548 bool isFPImm() const {
549 if (!isImm()) return false;
550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
551 if (!CE) return false;
552 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
553 return Val != -1;
554 }
Jim Grosbachea231912011-12-22 22:19:05 +0000555 bool isFBits16() const {
556 if (!isImm()) return false;
557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
558 if (!CE) return false;
559 int64_t Value = CE->getValue();
560 return Value >= 0 && Value <= 16;
561 }
562 bool isFBits32() const {
563 if (!isImm()) return false;
564 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
565 if (!CE) return false;
566 int64_t Value = CE->getValue();
567 return Value >= 1 && Value <= 32;
568 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000569 bool isImm8s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000570 if (!isImm()) return false;
Jim Grosbach7db8d692011-09-08 22:07:06 +0000571 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
572 if (!CE) return false;
573 int64_t Value = CE->getValue();
574 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
575 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000576 bool isImm0_1020s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000577 if (!isImm()) return false;
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000578 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
579 if (!CE) return false;
580 int64_t Value = CE->getValue();
581 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
582 }
583 bool isImm0_508s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000584 if (!isImm()) return false;
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
589 }
Jim Grosbach930f2f62012-04-05 20:57:13 +0000590 bool isImm0_508s4Neg() const {
591 if (!isImm()) return false;
592 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
593 if (!CE) return false;
594 int64_t Value = -CE->getValue();
595 // explicitly exclude zero. we want that to use the normal 0_508 version.
596 return ((Value & 3) == 0) && Value > 0 && Value <= 508;
597 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000598 bool isImm0_255() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000599 if (!isImm()) return false;
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
601 if (!CE) return false;
602 int64_t Value = CE->getValue();
603 return Value >= 0 && Value < 256;
604 }
Jim Grosbach930f2f62012-04-05 20:57:13 +0000605 bool isImm0_4095() const {
606 if (!isImm()) return false;
607 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
608 if (!CE) return false;
609 int64_t Value = CE->getValue();
610 return Value >= 0 && Value < 4096;
611 }
612 bool isImm0_4095Neg() const {
613 if (!isImm()) return false;
614 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
615 if (!CE) return false;
616 int64_t Value = -CE->getValue();
617 return Value > 0 && Value < 4096;
618 }
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000619 bool isImm0_1() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000620 if (!isImm()) return false;
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000621 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
622 if (!CE) return false;
623 int64_t Value = CE->getValue();
624 return Value >= 0 && Value < 2;
625 }
626 bool isImm0_3() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000627 if (!isImm()) return false;
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000628 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
629 if (!CE) return false;
630 int64_t Value = CE->getValue();
631 return Value >= 0 && Value < 4;
632 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000633 bool isImm0_7() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000634 if (!isImm()) return false;
Jim Grosbach31756c22011-07-13 22:01:08 +0000635 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
636 if (!CE) return false;
637 int64_t Value = CE->getValue();
638 return Value >= 0 && Value < 8;
639 }
640 bool isImm0_15() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000641 if (!isImm()) return false;
Jim Grosbach31756c22011-07-13 22:01:08 +0000642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
643 if (!CE) return false;
644 int64_t Value = CE->getValue();
645 return Value >= 0 && Value < 16;
646 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000647 bool isImm0_31() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000648 if (!isImm()) return false;
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value >= 0 && Value < 32;
653 }
Jim Grosbach00326402011-12-08 01:30:04 +0000654 bool isImm0_63() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000655 if (!isImm()) return false;
Jim Grosbach00326402011-12-08 01:30:04 +0000656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
657 if (!CE) return false;
658 int64_t Value = CE->getValue();
659 return Value >= 0 && Value < 64;
660 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000661 bool isImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000662 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
664 if (!CE) return false;
665 int64_t Value = CE->getValue();
666 return Value == 8;
667 }
668 bool isImm16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000669 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000670 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
671 if (!CE) return false;
672 int64_t Value = CE->getValue();
673 return Value == 16;
674 }
675 bool isImm32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000676 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000677 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
678 if (!CE) return false;
679 int64_t Value = CE->getValue();
680 return Value == 32;
681 }
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000682 bool isShrImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000683 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000684 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
685 if (!CE) return false;
686 int64_t Value = CE->getValue();
687 return Value > 0 && Value <= 8;
688 }
689 bool isShrImm16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000690 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000691 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
692 if (!CE) return false;
693 int64_t Value = CE->getValue();
694 return Value > 0 && Value <= 16;
695 }
696 bool isShrImm32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000697 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
699 if (!CE) return false;
700 int64_t Value = CE->getValue();
701 return Value > 0 && Value <= 32;
702 }
703 bool isShrImm64() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000704 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 if (!CE) return false;
707 int64_t Value = CE->getValue();
708 return Value > 0 && Value <= 64;
709 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000710 bool isImm1_7() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000711 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000712 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
713 if (!CE) return false;
714 int64_t Value = CE->getValue();
715 return Value > 0 && Value < 8;
716 }
717 bool isImm1_15() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000718 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000719 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
720 if (!CE) return false;
721 int64_t Value = CE->getValue();
722 return Value > 0 && Value < 16;
723 }
724 bool isImm1_31() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000725 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000726 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
727 if (!CE) return false;
728 int64_t Value = CE->getValue();
729 return Value > 0 && Value < 32;
730 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000731 bool isImm1_16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000732 if (!isImm()) return false;
Jim Grosbach475c6db2011-07-25 23:09:14 +0000733 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
734 if (!CE) return false;
735 int64_t Value = CE->getValue();
736 return Value > 0 && Value < 17;
737 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000738 bool isImm1_32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000739 if (!isImm()) return false;
Jim Grosbach801e0a32011-07-22 23:16:18 +0000740 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
741 if (!CE) return false;
742 int64_t Value = CE->getValue();
743 return Value > 0 && Value < 33;
744 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000745 bool isImm0_32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000746 if (!isImm()) return false;
Jim Grosbachc14871c2011-11-10 19:18:01 +0000747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value < 33;
751 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000752 bool isImm0_65535() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000753 if (!isImm()) return false;
Jim Grosbach975b6412011-07-13 20:10:10 +0000754 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
755 if (!CE) return false;
756 int64_t Value = CE->getValue();
757 return Value >= 0 && Value < 65536;
758 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000759 bool isImm0_65535Expr() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000760 if (!isImm()) return false;
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000761 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
762 // If it's not a constant expression, it'll generate a fixup and be
763 // handled later.
764 if (!CE) return true;
765 int64_t Value = CE->getValue();
766 return Value >= 0 && Value < 65536;
767 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000768 bool isImm24bit() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000769 if (!isImm()) return false;
Jim Grosbachf1637842011-07-26 16:24:27 +0000770 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
771 if (!CE) return false;
772 int64_t Value = CE->getValue();
773 return Value >= 0 && Value <= 0xffffff;
774 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000775 bool isImmThumbSR() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000776 if (!isImm()) return false;
Jim Grosbach46dd4132011-08-17 21:51:27 +0000777 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
778 if (!CE) return false;
779 int64_t Value = CE->getValue();
780 return Value > 0 && Value < 33;
781 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000782 bool isPKHLSLImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000783 if (!isImm()) return false;
Jim Grosbach27c1e252011-07-21 17:23:04 +0000784 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
785 if (!CE) return false;
786 int64_t Value = CE->getValue();
787 return Value >= 0 && Value < 32;
788 }
789 bool isPKHASRImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000790 if (!isImm()) return false;
Jim Grosbach27c1e252011-07-21 17:23:04 +0000791 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
792 if (!CE) return false;
793 int64_t Value = CE->getValue();
794 return Value > 0 && Value <= 32;
795 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000796 bool isARMSOImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000797 if (!isImm()) return false;
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000798 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
799 if (!CE) return false;
800 int64_t Value = CE->getValue();
801 return ARM_AM::getSOImmVal(Value) != -1;
802 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000803 bool isARMSOImmNot() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000804 if (!isImm()) return false;
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000805 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
806 if (!CE) return false;
807 int64_t Value = CE->getValue();
808 return ARM_AM::getSOImmVal(~Value) != -1;
809 }
Jim Grosbach30506252011-12-08 00:31:07 +0000810 bool isARMSOImmNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000811 if (!isImm()) return false;
Jim Grosbach30506252011-12-08 00:31:07 +0000812 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
813 if (!CE) return false;
814 int64_t Value = CE->getValue();
Jim Grosbachfdaab532012-03-30 19:59:02 +0000815 // Only use this when not representable as a plain so_imm.
816 return ARM_AM::getSOImmVal(Value) == -1 &&
817 ARM_AM::getSOImmVal(-Value) != -1;
Jim Grosbach30506252011-12-08 00:31:07 +0000818 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000819 bool isT2SOImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000820 if (!isImm()) return false;
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000821 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
822 if (!CE) return false;
823 int64_t Value = CE->getValue();
824 return ARM_AM::getT2SOImmVal(Value) != -1;
825 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000826 bool isT2SOImmNot() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000827 if (!isImm()) return false;
Jim Grosbachb009a872011-10-28 22:36:30 +0000828 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
829 if (!CE) return false;
830 int64_t Value = CE->getValue();
831 return ARM_AM::getT2SOImmVal(~Value) != -1;
832 }
Jim Grosbach30506252011-12-08 00:31:07 +0000833 bool isT2SOImmNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000834 if (!isImm()) return false;
Jim Grosbach30506252011-12-08 00:31:07 +0000835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
836 if (!CE) return false;
837 int64_t Value = CE->getValue();
Jim Grosbachfdaab532012-03-30 19:59:02 +0000838 // Only use this when not representable as a plain so_imm.
839 return ARM_AM::getT2SOImmVal(Value) == -1 &&
840 ARM_AM::getT2SOImmVal(-Value) != -1;
Jim Grosbach30506252011-12-08 00:31:07 +0000841 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000842 bool isSetEndImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000843 if (!isImm()) return false;
Jim Grosbach0a547702011-07-22 17:44:50 +0000844 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
845 if (!CE) return false;
846 int64_t Value = CE->getValue();
847 return Value == 1 || Value == 0;
848 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000849 bool isReg() const { return Kind == k_Register; }
850 bool isRegList() const { return Kind == k_RegisterList; }
851 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
852 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
853 bool isToken() const { return Kind == k_Token; }
854 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
855 bool isMemory() const { return Kind == k_Memory; }
856 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
857 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
858 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
859 bool isRotImm() const { return Kind == k_RotateImmediate; }
860 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
861 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000862 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000863 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000864 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000865 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000866 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000867 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000868 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000869 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
870 (alignOK || Memory.Alignment == 0);
871 }
Jim Grosbach94298a92012-01-18 22:46:46 +0000872 bool isMemPCRelImm12() const {
873 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
874 return false;
875 // Base register must be PC.
876 if (Memory.BaseRegNum != ARM::PC)
877 return false;
878 // Immediate offset in range [-4095, 4095].
879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
881 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
882 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000883 bool isAlignedMemory() const {
884 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000885 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000886 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000887 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000888 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000889 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000890 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000891 if (!Memory.OffsetImm) return true;
892 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000893 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000894 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000895 bool isAM2OffsetImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000896 if (!isImm()) return false;
Jim Grosbachcd17c122011-08-04 23:01:30 +0000897 // Immediate offset in range [-4095, 4095].
898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
899 if (!CE) return false;
900 int64_t Val = CE->getValue();
901 return Val > -4096 && Val < 4096;
902 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000903 bool isAddrMode3() const {
Jim Grosbach8648c102011-12-19 23:06:24 +0000904 // If we have an immediate that's not a constant, treat it as a label
905 // reference needing a fixup. If it is a constant, it's something else
906 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000907 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +0000908 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000909 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000910 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000911 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000912 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000913 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000914 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000915 if (!Memory.OffsetImm) return true;
916 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000917 return Val > -256 && Val < 256;
918 }
919 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000920 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000921 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000922 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000923 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
924 // Immediate offset in range [-255, 255].
925 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
926 if (!CE) return false;
927 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000928 // Special case, #-0 is INT32_MIN.
929 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000930 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000931 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000932 // If we have an immediate that's not a constant, treat it as a label
933 // reference needing a fixup. If it is a constant, it's something else
934 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000935 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000936 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000937 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000938 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000939 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000940 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000941 if (!Memory.OffsetImm) return true;
942 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000943 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000944 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000945 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000946 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000947 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000948 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000949 return false;
950 return true;
951 }
952 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000953 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000954 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
955 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000956 return false;
957 return true;
958 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000959 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000960 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000961 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000962 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000963 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000964 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000965 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
966 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000967 return false;
968 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000969 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000970 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000971 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000972 return false;
973 return true;
974 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000975 bool isMemThumbRR() const {
976 // Thumb reg+reg addressing is simple. Just two registers, a base and
977 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000978 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000979 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000980 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000981 return isARMLowRegister(Memory.BaseRegNum) &&
982 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000983 }
984 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000985 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000986 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000987 return false;
988 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000989 if (!Memory.OffsetImm) return true;
990 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000991 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
992 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000993 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000994 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000995 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000996 return false;
997 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000998 if (!Memory.OffsetImm) return true;
999 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +00001000 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1001 }
Jim Grosbacha32c7532011-08-19 18:49:59 +00001002 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +00001003 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +00001004 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +00001005 return false;
1006 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +00001007 if (!Memory.OffsetImm) return true;
1008 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +00001009 return Val >= 0 && Val <= 31;
1010 }
Jim Grosbach23983d62011-08-19 18:13:48 +00001011 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001012 if (!isMemory() || Memory.OffsetRegNum != 0 ||
1013 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +00001014 return false;
1015 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001016 if (!Memory.OffsetImm) return true;
1017 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +00001018 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +00001019 }
Jim Grosbach7db8d692011-09-08 22:07:06 +00001020 bool isMemImm8s4Offset() const {
Jim Grosbach8648c102011-12-19 23:06:24 +00001021 // If we have an immediate that's not a constant, treat it as a label
1022 // reference needing a fixup. If it is a constant, it's something else
1023 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001024 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +00001025 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001026 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +00001027 return false;
1028 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001029 if (!Memory.OffsetImm) return true;
1030 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +00001031 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1032 }
Jim Grosbacha05627e2011-09-09 18:37:27 +00001033 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001034 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +00001035 return false;
1036 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001037 if (!Memory.OffsetImm) return true;
1038 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001039 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1040 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001041 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001042 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001043 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001044 // Base reg of PC isn't allowed for these encodings.
1045 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001046 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001047 if (!Memory.OffsetImm) return true;
1048 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001049 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001050 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001051 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001052 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001053 return false;
1054 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001055 if (!Memory.OffsetImm) return true;
1056 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001057 return Val >= 0 && Val < 256;
1058 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001059 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001060 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001061 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001062 // Base reg of PC isn't allowed for these encodings.
1063 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001064 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001065 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001066 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001067 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001068 }
1069 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001070 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001071 return false;
1072 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001073 if (!Memory.OffsetImm) return true;
1074 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001075 return (Val >= 0 && Val < 4096);
1076 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001077 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001078 // If we have an immediate that's not a constant, treat it as a label
1079 // reference needing a fixup. If it is a constant, it's something else
1080 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001081 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001082 return true;
1083
Jim Grosbacha95ec992011-10-11 17:29:55 +00001084 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001085 return false;
1086 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001087 if (!Memory.OffsetImm) return true;
1088 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001089 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001090 }
1091 bool isPostIdxImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001092 if (!isImm()) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001093 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1094 if (!CE) return false;
1095 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001096 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001097 }
Jim Grosbach93981412011-10-11 21:55:36 +00001098 bool isPostIdxImm8s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001099 if (!isImm()) return false;
Jim Grosbach93981412011-10-11 21:55:36 +00001100 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1101 if (!CE) return false;
1102 int64_t Val = CE->getValue();
1103 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1104 (Val == INT32_MIN);
1105 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001106
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001107 bool isMSRMask() const { return Kind == k_MSRMask; }
1108 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001109
Jim Grosbach741cd732011-10-17 22:26:03 +00001110 // NEON operands.
Jim Grosbach2f50e922011-12-15 21:44:33 +00001111 bool isSingleSpacedVectorList() const {
1112 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1113 }
1114 bool isDoubleSpacedVectorList() const {
1115 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1116 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001117 bool isVecListOneD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001118 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001119 return VectorList.Count == 1;
1120 }
1121
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001122 bool isVecListDPair() const {
1123 if (!isSingleSpacedVectorList()) return false;
1124 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1125 .contains(VectorList.RegNum));
1126 }
1127
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001128 bool isVecListThreeD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001129 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001130 return VectorList.Count == 3;
1131 }
1132
Jim Grosbach846bcff2011-10-21 20:35:01 +00001133 bool isVecListFourD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001134 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach846bcff2011-10-21 20:35:01 +00001135 return VectorList.Count == 4;
1136 }
1137
Jim Grosbache5307f92012-03-05 21:43:40 +00001138 bool isVecListDPairSpaced() const {
Kevin Enderby816ca272012-03-20 17:41:51 +00001139 if (isSingleSpacedVectorList()) return false;
Jim Grosbache5307f92012-03-05 21:43:40 +00001140 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1141 .contains(VectorList.RegNum));
1142 }
1143
Jim Grosbachac2af3f2012-01-23 23:20:46 +00001144 bool isVecListThreeQ() const {
1145 if (!isDoubleSpacedVectorList()) return false;
1146 return VectorList.Count == 3;
1147 }
1148
Jim Grosbach1e946a42012-01-24 00:43:12 +00001149 bool isVecListFourQ() const {
1150 if (!isDoubleSpacedVectorList()) return false;
1151 return VectorList.Count == 4;
1152 }
1153
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001154 bool isSingleSpacedVectorAllLanes() const {
1155 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1156 }
1157 bool isDoubleSpacedVectorAllLanes() const {
1158 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1159 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001160 bool isVecListOneDAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001161 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001162 return VectorList.Count == 1;
1163 }
1164
Jim Grosbach13a292c2012-03-06 22:01:44 +00001165 bool isVecListDPairAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001166 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach13a292c2012-03-06 22:01:44 +00001167 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1168 .contains(VectorList.RegNum));
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001169 }
1170
Jim Grosbached428bc2012-03-06 23:10:38 +00001171 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001172 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001173 return VectorList.Count == 2;
1174 }
1175
Jim Grosbachb78403c2012-01-24 23:47:04 +00001176 bool isVecListThreeDAllLanes() const {
1177 if (!isSingleSpacedVectorAllLanes()) return false;
1178 return VectorList.Count == 3;
1179 }
1180
1181 bool isVecListThreeQAllLanes() const {
1182 if (!isDoubleSpacedVectorAllLanes()) return false;
1183 return VectorList.Count == 3;
1184 }
1185
Jim Grosbach086cbfa2012-01-25 00:01:08 +00001186 bool isVecListFourDAllLanes() const {
1187 if (!isSingleSpacedVectorAllLanes()) return false;
1188 return VectorList.Count == 4;
1189 }
1190
1191 bool isVecListFourQAllLanes() const {
1192 if (!isDoubleSpacedVectorAllLanes()) return false;
1193 return VectorList.Count == 4;
1194 }
1195
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001196 bool isSingleSpacedVectorIndexed() const {
1197 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1198 }
1199 bool isDoubleSpacedVectorIndexed() const {
1200 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1201 }
Jim Grosbach04945c42011-12-02 00:35:16 +00001202 bool isVecListOneDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001203 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach04945c42011-12-02 00:35:16 +00001204 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1205 }
1206
Jim Grosbachda511042011-12-14 23:35:06 +00001207 bool isVecListOneDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001208 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001209 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1210 }
1211
1212 bool isVecListOneDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001213 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001214 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1215 }
1216
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001217 bool isVecListTwoDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001218 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001219 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1220 }
1221
Jim Grosbachda511042011-12-14 23:35:06 +00001222 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001223 if (!isSingleSpacedVectorIndexed()) return false;
1224 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1225 }
1226
1227 bool isVecListTwoQWordIndexed() const {
1228 if (!isDoubleSpacedVectorIndexed()) return false;
1229 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1230 }
1231
1232 bool isVecListTwoQHWordIndexed() const {
1233 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001234 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1235 }
1236
1237 bool isVecListTwoDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001238 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001239 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1240 }
1241
Jim Grosbacha8b444b2012-01-23 21:53:26 +00001242 bool isVecListThreeDByteIndexed() const {
1243 if (!isSingleSpacedVectorIndexed()) return false;
1244 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1245 }
1246
1247 bool isVecListThreeDHWordIndexed() const {
1248 if (!isSingleSpacedVectorIndexed()) return false;
1249 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1250 }
1251
1252 bool isVecListThreeQWordIndexed() const {
1253 if (!isDoubleSpacedVectorIndexed()) return false;
1254 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1255 }
1256
1257 bool isVecListThreeQHWordIndexed() const {
1258 if (!isDoubleSpacedVectorIndexed()) return false;
1259 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1260 }
1261
1262 bool isVecListThreeDWordIndexed() const {
1263 if (!isSingleSpacedVectorIndexed()) return false;
1264 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1265 }
1266
Jim Grosbach14952a02012-01-24 18:37:25 +00001267 bool isVecListFourDByteIndexed() const {
1268 if (!isSingleSpacedVectorIndexed()) return false;
1269 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1270 }
1271
1272 bool isVecListFourDHWordIndexed() const {
1273 if (!isSingleSpacedVectorIndexed()) return false;
1274 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1275 }
1276
1277 bool isVecListFourQWordIndexed() const {
1278 if (!isDoubleSpacedVectorIndexed()) return false;
1279 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1280 }
1281
1282 bool isVecListFourQHWordIndexed() const {
1283 if (!isDoubleSpacedVectorIndexed()) return false;
1284 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1285 }
1286
1287 bool isVecListFourDWordIndexed() const {
1288 if (!isSingleSpacedVectorIndexed()) return false;
1289 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1290 }
1291
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001292 bool isVectorIndex8() const {
1293 if (Kind != k_VectorIndex) return false;
1294 return VectorIndex.Val < 8;
1295 }
1296 bool isVectorIndex16() const {
1297 if (Kind != k_VectorIndex) return false;
1298 return VectorIndex.Val < 4;
1299 }
1300 bool isVectorIndex32() const {
1301 if (Kind != k_VectorIndex) return false;
1302 return VectorIndex.Val < 2;
1303 }
1304
Jim Grosbach741cd732011-10-17 22:26:03 +00001305 bool isNEONi8splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001306 if (!isImm()) return false;
Jim Grosbach741cd732011-10-17 22:26:03 +00001307 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1308 // Must be a constant.
1309 if (!CE) return false;
1310 int64_t Value = CE->getValue();
1311 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1312 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001313 return Value >= 0 && Value < 256;
1314 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001315
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001316 bool isNEONi16splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001317 if (!isImm()) return false;
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001318 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1319 // Must be a constant.
1320 if (!CE) return false;
1321 int64_t Value = CE->getValue();
1322 // i16 value in the range [0,255] or [0x0100, 0xff00]
1323 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1324 }
1325
Jim Grosbach8211c052011-10-18 00:22:00 +00001326 bool isNEONi32splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001327 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001328 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1329 // Must be a constant.
1330 if (!CE) return false;
1331 int64_t Value = CE->getValue();
1332 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1333 return (Value >= 0 && Value < 256) ||
1334 (Value >= 0x0100 && Value <= 0xff00) ||
1335 (Value >= 0x010000 && Value <= 0xff0000) ||
1336 (Value >= 0x01000000 && Value <= 0xff000000);
1337 }
1338
1339 bool isNEONi32vmov() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001340 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001341 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1342 // Must be a constant.
1343 if (!CE) return false;
1344 int64_t Value = CE->getValue();
1345 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1346 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1347 return (Value >= 0 && Value < 256) ||
1348 (Value >= 0x0100 && Value <= 0xff00) ||
1349 (Value >= 0x010000 && Value <= 0xff0000) ||
1350 (Value >= 0x01000000 && Value <= 0xff000000) ||
1351 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1352 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1353 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00001354 bool isNEONi32vmovNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001355 if (!isImm()) return false;
Jim Grosbach045b6c72011-12-19 23:51:07 +00001356 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1357 // Must be a constant.
1358 if (!CE) return false;
1359 int64_t Value = ~CE->getValue();
1360 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1361 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1362 return (Value >= 0 && Value < 256) ||
1363 (Value >= 0x0100 && Value <= 0xff00) ||
1364 (Value >= 0x010000 && Value <= 0xff0000) ||
1365 (Value >= 0x01000000 && Value <= 0xff000000) ||
1366 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1367 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1368 }
Jim Grosbach8211c052011-10-18 00:22:00 +00001369
Jim Grosbache4454e02011-10-18 16:18:11 +00001370 bool isNEONi64splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001371 if (!isImm()) return false;
Jim Grosbache4454e02011-10-18 16:18:11 +00001372 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1373 // Must be a constant.
1374 if (!CE) return false;
1375 uint64_t Value = CE->getValue();
1376 // i64 value with each byte being either 0 or 0xff.
1377 for (unsigned i = 0; i < 8; ++i)
1378 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1379 return true;
1380 }
1381
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001382 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001383 // Add as immediates when possible. Null MCExpr = 0.
1384 if (Expr == 0)
1385 Inst.addOperand(MCOperand::CreateImm(0));
1386 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001387 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1388 else
1389 Inst.addOperand(MCOperand::CreateExpr(Expr));
1390 }
1391
Daniel Dunbard8042b72010-08-11 06:36:53 +00001392 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001393 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001394 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001395 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1396 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001397 }
1398
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001399 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1400 assert(N == 1 && "Invalid number of operands!");
1401 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1402 }
1403
Jim Grosbach48399582011-10-12 17:34:41 +00001404 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1407 }
1408
1409 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1412 }
1413
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001414 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
1416 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1417 }
1418
1419 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 1 && "Invalid number of operands!");
1421 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1422 }
1423
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001424 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 Inst.addOperand(MCOperand::CreateReg(getReg()));
1427 }
1428
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001429 void addRegOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
1431 Inst.addOperand(MCOperand::CreateReg(getReg()));
1432 }
1433
Jim Grosbachac798e12011-07-25 20:49:51 +00001434 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001435 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001436 assert(isRegShiftedReg() &&
1437 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001438 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1439 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001440 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001441 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001442 }
1443
Jim Grosbachac798e12011-07-25 20:49:51 +00001444 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001445 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001446 assert(isRegShiftedImm() &&
1447 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001448 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Richard Bartonba5b0cc2012-04-25 18:00:18 +00001449 // Shift of #32 is encoded as 0 where permitted
1450 unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm);
Owen Andersonb595ed02011-07-21 18:54:16 +00001451 Inst.addOperand(MCOperand::CreateImm(
Richard Bartonba5b0cc2012-04-25 18:00:18 +00001452 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001453 }
1454
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001455 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001456 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001457 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1458 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001459 }
1460
Bill Wendling8d2aa032010-11-08 23:49:57 +00001461 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001462 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001463 const SmallVectorImpl<unsigned> &RegList = getRegList();
1464 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001465 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1466 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001467 }
1468
Bill Wendling9898ac92010-11-17 04:32:08 +00001469 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1470 addRegListOperands(Inst, N);
1471 }
1472
1473 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1474 addRegListOperands(Inst, N);
1475 }
1476
Jim Grosbach833b9d32011-07-27 20:15:40 +00001477 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1480 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1481 }
1482
Jim Grosbach864b6092011-07-28 21:34:26 +00001483 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485 // Munge the lsb/width into a bitfield mask.
1486 unsigned lsb = Bitfield.LSB;
1487 unsigned width = Bitfield.Width;
1488 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1489 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1490 (32 - (lsb + width)));
1491 Inst.addOperand(MCOperand::CreateImm(Mask));
1492 }
1493
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001494 void addImmOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 addExpr(Inst, getImm());
1497 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001498
Jim Grosbachea231912011-12-22 22:19:05 +00001499 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1502 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1503 }
1504
1505 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1506 assert(N == 1 && "Invalid number of operands!");
1507 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1508 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1509 }
1510
Jim Grosbache7fbce72011-10-03 23:38:36 +00001511 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 1 && "Invalid number of operands!");
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00001513 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1514 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1515 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbache7fbce72011-10-03 23:38:36 +00001516 }
1517
Jim Grosbach7db8d692011-09-08 22:07:06 +00001518 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1519 assert(N == 1 && "Invalid number of operands!");
1520 // FIXME: We really want to scale the value here, but the LDRD/STRD
1521 // instruction don't encode operands that way yet.
1522 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1523 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1524 }
1525
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001526 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1527 assert(N == 1 && "Invalid number of operands!");
1528 // The immediate is scaled by four in the encoding and is stored
1529 // in the MCInst as such. Lop off the low two bits here.
1530 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1531 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1532 }
1533
Jim Grosbach930f2f62012-04-05 20:57:13 +00001534 void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 1 && "Invalid number of operands!");
1536 // The immediate is scaled by four in the encoding and is stored
1537 // in the MCInst as such. Lop off the low two bits here.
1538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1539 Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
1540 }
1541
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001542 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544 // The immediate is scaled by four in the encoding and is stored
1545 // in the MCInst as such. Lop off the low two bits here.
1546 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1547 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1548 }
1549
Jim Grosbach475c6db2011-07-25 23:09:14 +00001550 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552 // The constant encodes as the immediate-1, and we store in the instruction
1553 // the bits as encoded, so subtract off one here.
1554 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1555 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1556 }
1557
Jim Grosbach801e0a32011-07-22 23:16:18 +00001558 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1559 assert(N == 1 && "Invalid number of operands!");
1560 // The constant encodes as the immediate-1, and we store in the instruction
1561 // the bits as encoded, so subtract off one here.
1562 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1563 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1564 }
1565
Jim Grosbach46dd4132011-08-17 21:51:27 +00001566 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 1 && "Invalid number of operands!");
1568 // The constant encodes as the immediate, except for 32, which encodes as
1569 // zero.
1570 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1571 unsigned Imm = CE->getValue();
1572 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1573 }
1574
Jim Grosbach27c1e252011-07-21 17:23:04 +00001575 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1578 // the instruction as well.
1579 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1580 int Val = CE->getValue();
1581 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1582 }
1583
Jim Grosbachb009a872011-10-28 22:36:30 +00001584 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1585 assert(N == 1 && "Invalid number of operands!");
1586 // The operand is actually a t2_so_imm, but we have its bitwise
1587 // negation in the assembly source, so twiddle it here.
1588 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1589 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1590 }
1591
Jim Grosbach30506252011-12-08 00:31:07 +00001592 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1593 assert(N == 1 && "Invalid number of operands!");
1594 // The operand is actually a t2_so_imm, but we have its
1595 // negation in the assembly source, so twiddle it here.
1596 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1597 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1598 }
1599
Jim Grosbach930f2f62012-04-05 20:57:13 +00001600 void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
1601 assert(N == 1 && "Invalid number of operands!");
1602 // The operand is actually an imm0_4095, but we have its
1603 // negation in the assembly source, so twiddle it here.
1604 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1605 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1606 }
1607
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001608 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1609 assert(N == 1 && "Invalid number of operands!");
1610 // The operand is actually a so_imm, but we have its bitwise
1611 // negation in the assembly source, so twiddle it here.
1612 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1613 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1614 }
1615
Jim Grosbach30506252011-12-08 00:31:07 +00001616 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1617 assert(N == 1 && "Invalid number of operands!");
1618 // The operand is actually a so_imm, but we have its
1619 // negation in the assembly source, so twiddle it here.
1620 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1621 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1622 }
1623
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001624 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1625 assert(N == 1 && "Invalid number of operands!");
1626 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1627 }
1628
Jim Grosbachd3595712011-08-03 23:50:40 +00001629 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1630 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001631 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001632 }
1633
Jim Grosbach94298a92012-01-18 22:46:46 +00001634 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1635 assert(N == 1 && "Invalid number of operands!");
1636 int32_t Imm = Memory.OffsetImm->getValue();
1637 // FIXME: Handle #-0
1638 if (Imm == INT32_MIN) Imm = 0;
1639 Inst.addOperand(MCOperand::CreateImm(Imm));
1640 }
1641
Jim Grosbacha95ec992011-10-11 17:29:55 +00001642 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1643 assert(N == 2 && "Invalid number of operands!");
1644 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1645 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1646 }
1647
Jim Grosbachd3595712011-08-03 23:50:40 +00001648 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1649 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001650 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1651 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001652 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1653 // Special case for #-0
1654 if (Val == INT32_MIN) Val = 0;
1655 if (Val < 0) Val = -Val;
1656 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1657 } else {
1658 // For register offset, we encode the shift type and negation flag
1659 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001660 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1661 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001662 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001663 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1664 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001665 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001666 }
1667
Jim Grosbachcd17c122011-08-04 23:01:30 +00001668 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1669 assert(N == 2 && "Invalid number of operands!");
1670 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1671 assert(CE && "non-constant AM2OffsetImm operand!");
1672 int32_t Val = CE->getValue();
1673 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1674 // Special case for #-0
1675 if (Val == INT32_MIN) Val = 0;
1676 if (Val < 0) Val = -Val;
1677 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1678 Inst.addOperand(MCOperand::CreateReg(0));
1679 Inst.addOperand(MCOperand::CreateImm(Val));
1680 }
1681
Jim Grosbach5b96b802011-08-10 20:29:19 +00001682 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1683 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001684 // If we have an immediate that's not a constant, treat it as a label
1685 // reference needing a fixup. If it is a constant, it's something else
1686 // and we reject it.
1687 if (isImm()) {
1688 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1689 Inst.addOperand(MCOperand::CreateReg(0));
1690 Inst.addOperand(MCOperand::CreateImm(0));
1691 return;
1692 }
1693
Jim Grosbach871dff72011-10-11 15:59:20 +00001694 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1695 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001696 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1697 // Special case for #-0
1698 if (Val == INT32_MIN) Val = 0;
1699 if (Val < 0) Val = -Val;
1700 Val = ARM_AM::getAM3Opc(AddSub, Val);
1701 } else {
1702 // For register offset, we encode the shift type and negation flag
1703 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001704 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001705 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001706 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1707 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001708 Inst.addOperand(MCOperand::CreateImm(Val));
1709 }
1710
1711 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1712 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001713 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001714 int32_t Val =
1715 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1716 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1717 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001718 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001719 }
1720
1721 // Constant offset.
1722 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1723 int32_t Val = CE->getValue();
1724 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1725 // Special case for #-0
1726 if (Val == INT32_MIN) Val = 0;
1727 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001728 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001729 Inst.addOperand(MCOperand::CreateReg(0));
1730 Inst.addOperand(MCOperand::CreateImm(Val));
1731 }
1732
Jim Grosbachd3595712011-08-03 23:50:40 +00001733 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1734 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001735 // If we have an immediate that's not a constant, treat it as a label
1736 // reference needing a fixup. If it is a constant, it's something else
1737 // and we reject it.
1738 if (isImm()) {
1739 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1740 Inst.addOperand(MCOperand::CreateImm(0));
1741 return;
1742 }
1743
Jim Grosbachd3595712011-08-03 23:50:40 +00001744 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001745 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001746 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1747 // Special case for #-0
1748 if (Val == INT32_MIN) Val = 0;
1749 if (Val < 0) Val = -Val;
1750 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001751 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001752 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001753 }
1754
Jim Grosbach7db8d692011-09-08 22:07:06 +00001755 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1756 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001757 // If we have an immediate that's not a constant, treat it as a label
1758 // reference needing a fixup. If it is a constant, it's something else
1759 // and we reject it.
1760 if (isImm()) {
1761 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1762 Inst.addOperand(MCOperand::CreateImm(0));
1763 return;
1764 }
1765
Jim Grosbach871dff72011-10-11 15:59:20 +00001766 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1767 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001768 Inst.addOperand(MCOperand::CreateImm(Val));
1769 }
1770
Jim Grosbacha05627e2011-09-09 18:37:27 +00001771 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1772 assert(N == 2 && "Invalid number of operands!");
1773 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001774 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1775 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001776 Inst.addOperand(MCOperand::CreateImm(Val));
1777 }
1778
Jim Grosbachd3595712011-08-03 23:50:40 +00001779 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1780 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001781 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1782 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001783 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001784 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001785
Jim Grosbach2392c532011-09-07 23:39:14 +00001786 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1787 addMemImm8OffsetOperands(Inst, N);
1788 }
1789
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001790 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001791 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001792 }
1793
1794 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1795 assert(N == 2 && "Invalid number of operands!");
1796 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001797 if (isImm()) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001798 addExpr(Inst, getImm());
1799 Inst.addOperand(MCOperand::CreateImm(0));
1800 return;
1801 }
1802
1803 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001804 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1805 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001806 Inst.addOperand(MCOperand::CreateImm(Val));
1807 }
1808
Jim Grosbachd3595712011-08-03 23:50:40 +00001809 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1810 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001811 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001812 if (isImm()) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001813 addExpr(Inst, getImm());
1814 Inst.addOperand(MCOperand::CreateImm(0));
1815 return;
1816 }
1817
1818 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001819 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1820 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001821 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001822 }
Bill Wendling811c9362010-11-30 07:44:32 +00001823
Jim Grosbach05541f42011-09-19 22:21:13 +00001824 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1825 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001826 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1827 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001828 }
1829
1830 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1831 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001832 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1833 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001834 }
1835
Jim Grosbachd3595712011-08-03 23:50:40 +00001836 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1837 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001838 unsigned Val =
1839 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1840 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001841 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1842 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001843 Inst.addOperand(MCOperand::CreateImm(Val));
1844 }
1845
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001846 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1847 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001848 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1849 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1850 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001851 }
1852
Jim Grosbachd3595712011-08-03 23:50:40 +00001853 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1854 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001855 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1856 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001857 }
1858
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001859 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1860 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001861 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1862 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001863 Inst.addOperand(MCOperand::CreateImm(Val));
1864 }
1865
Jim Grosbach26d35872011-08-19 18:55:51 +00001866 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1867 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001868 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1869 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001870 Inst.addOperand(MCOperand::CreateImm(Val));
1871 }
1872
Jim Grosbacha32c7532011-08-19 18:49:59 +00001873 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1874 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001875 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1876 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001877 Inst.addOperand(MCOperand::CreateImm(Val));
1878 }
1879
Jim Grosbach23983d62011-08-19 18:13:48 +00001880 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1881 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001882 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1883 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001884 Inst.addOperand(MCOperand::CreateImm(Val));
1885 }
1886
Jim Grosbachd3595712011-08-03 23:50:40 +00001887 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1888 assert(N == 1 && "Invalid number of operands!");
1889 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1890 assert(CE && "non-constant post-idx-imm8 operand!");
1891 int Imm = CE->getValue();
1892 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001893 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001894 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1895 Inst.addOperand(MCOperand::CreateImm(Imm));
1896 }
1897
Jim Grosbach93981412011-10-11 21:55:36 +00001898 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1899 assert(N == 1 && "Invalid number of operands!");
1900 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1901 assert(CE && "non-constant post-idx-imm8s4 operand!");
1902 int Imm = CE->getValue();
1903 bool isAdd = Imm >= 0;
1904 if (Imm == INT32_MIN) Imm = 0;
1905 // Immediate is scaled by 4.
1906 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1907 Inst.addOperand(MCOperand::CreateImm(Imm));
1908 }
1909
Jim Grosbachd3595712011-08-03 23:50:40 +00001910 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1911 assert(N == 2 && "Invalid number of operands!");
1912 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001913 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1914 }
1915
1916 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1917 assert(N == 2 && "Invalid number of operands!");
1918 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1919 // The sign, shift type, and shift amount are encoded in a single operand
1920 // using the AM2 encoding helpers.
1921 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1922 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1923 PostIdxReg.ShiftTy);
1924 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001925 }
1926
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001927 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1928 assert(N == 1 && "Invalid number of operands!");
1929 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1930 }
1931
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001932 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1933 assert(N == 1 && "Invalid number of operands!");
1934 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1935 }
1936
Jim Grosbach182b6a02011-11-29 23:51:09 +00001937 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001938 assert(N == 1 && "Invalid number of operands!");
1939 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1940 }
1941
Jim Grosbach04945c42011-12-02 00:35:16 +00001942 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1943 assert(N == 2 && "Invalid number of operands!");
1944 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1945 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1946 }
1947
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001948 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1949 assert(N == 1 && "Invalid number of operands!");
1950 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1951 }
1952
1953 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1954 assert(N == 1 && "Invalid number of operands!");
1955 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1956 }
1957
1958 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1959 assert(N == 1 && "Invalid number of operands!");
1960 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1961 }
1962
Jim Grosbach741cd732011-10-17 22:26:03 +00001963 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1964 assert(N == 1 && "Invalid number of operands!");
1965 // The immediate encodes the type of constant as well as the value.
1966 // Mask in that this is an i8 splat.
1967 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1968 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1969 }
1970
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001971 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1972 assert(N == 1 && "Invalid number of operands!");
1973 // The immediate encodes the type of constant as well as the value.
1974 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1975 unsigned Value = CE->getValue();
1976 if (Value >= 256)
1977 Value = (Value >> 8) | 0xa00;
1978 else
1979 Value |= 0x800;
1980 Inst.addOperand(MCOperand::CreateImm(Value));
1981 }
1982
Jim Grosbach8211c052011-10-18 00:22:00 +00001983 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1984 assert(N == 1 && "Invalid number of operands!");
1985 // The immediate encodes the type of constant as well as the value.
1986 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1987 unsigned Value = CE->getValue();
1988 if (Value >= 256 && Value <= 0xff00)
1989 Value = (Value >> 8) | 0x200;
1990 else if (Value > 0xffff && Value <= 0xff0000)
1991 Value = (Value >> 16) | 0x400;
1992 else if (Value > 0xffffff)
1993 Value = (Value >> 24) | 0x600;
1994 Inst.addOperand(MCOperand::CreateImm(Value));
1995 }
1996
1997 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1998 assert(N == 1 && "Invalid number of operands!");
1999 // The immediate encodes the type of constant as well as the value.
2000 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2001 unsigned Value = CE->getValue();
2002 if (Value >= 256 && Value <= 0xffff)
2003 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2004 else if (Value > 0xffff && Value <= 0xffffff)
2005 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2006 else if (Value > 0xffffff)
2007 Value = (Value >> 24) | 0x600;
2008 Inst.addOperand(MCOperand::CreateImm(Value));
2009 }
2010
Jim Grosbach045b6c72011-12-19 23:51:07 +00002011 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2012 assert(N == 1 && "Invalid number of operands!");
2013 // The immediate encodes the type of constant as well as the value.
2014 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2015 unsigned Value = ~CE->getValue();
2016 if (Value >= 256 && Value <= 0xffff)
2017 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2018 else if (Value > 0xffff && Value <= 0xffffff)
2019 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2020 else if (Value > 0xffffff)
2021 Value = (Value >> 24) | 0x600;
2022 Inst.addOperand(MCOperand::CreateImm(Value));
2023 }
2024
Jim Grosbache4454e02011-10-18 16:18:11 +00002025 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2026 assert(N == 1 && "Invalid number of operands!");
2027 // The immediate encodes the type of constant as well as the value.
2028 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2029 uint64_t Value = CE->getValue();
2030 unsigned Imm = 0;
2031 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2032 Imm |= (Value & 1) << i;
2033 }
2034 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
2035 }
2036
Jim Grosbach602aa902011-07-13 15:34:57 +00002037 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00002038
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002039 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002040 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002041 Op->ITMask.Mask = Mask;
2042 Op->StartLoc = S;
2043 Op->EndLoc = S;
2044 return Op;
2045 }
2046
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002047 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002048 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00002049 Op->CC.Val = CC;
2050 Op->StartLoc = S;
2051 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002052 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00002053 }
2054
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002055 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002056 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002057 Op->Cop.Val = CopVal;
2058 Op->StartLoc = S;
2059 Op->EndLoc = S;
2060 return Op;
2061 }
2062
2063 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002064 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002065 Op->Cop.Val = CopVal;
2066 Op->StartLoc = S;
2067 Op->EndLoc = S;
2068 return Op;
2069 }
2070
Jim Grosbach48399582011-10-12 17:34:41 +00002071 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2072 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2073 Op->Cop.Val = Val;
2074 Op->StartLoc = S;
2075 Op->EndLoc = E;
2076 return Op;
2077 }
2078
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002079 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002080 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002081 Op->Reg.RegNum = RegNum;
2082 Op->StartLoc = S;
2083 Op->EndLoc = S;
2084 return Op;
2085 }
2086
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002087 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002088 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002089 Op->Tok.Data = Str.data();
2090 Op->Tok.Length = Str.size();
2091 Op->StartLoc = S;
2092 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002093 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002094 }
2095
Bill Wendling2063b842010-11-18 23:43:05 +00002096 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002097 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002098 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002099 Op->StartLoc = S;
2100 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002101 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002102 }
2103
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002104 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2105 unsigned SrcReg,
2106 unsigned ShiftReg,
2107 unsigned ShiftImm,
2108 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002109 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00002110 Op->RegShiftedReg.ShiftTy = ShTy;
2111 Op->RegShiftedReg.SrcReg = SrcReg;
2112 Op->RegShiftedReg.ShiftReg = ShiftReg;
2113 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002114 Op->StartLoc = S;
2115 Op->EndLoc = E;
2116 return Op;
2117 }
2118
Owen Andersonb595ed02011-07-21 18:54:16 +00002119 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2120 unsigned SrcReg,
2121 unsigned ShiftImm,
2122 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002123 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00002124 Op->RegShiftedImm.ShiftTy = ShTy;
2125 Op->RegShiftedImm.SrcReg = SrcReg;
2126 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00002127 Op->StartLoc = S;
2128 Op->EndLoc = E;
2129 return Op;
2130 }
2131
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002132 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002133 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002134 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002135 Op->ShifterImm.isASR = isASR;
2136 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002137 Op->StartLoc = S;
2138 Op->EndLoc = E;
2139 return Op;
2140 }
2141
Jim Grosbach833b9d32011-07-27 20:15:40 +00002142 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002143 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00002144 Op->RotImm.Imm = Imm;
2145 Op->StartLoc = S;
2146 Op->EndLoc = E;
2147 return Op;
2148 }
2149
Jim Grosbach864b6092011-07-28 21:34:26 +00002150 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2151 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002152 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00002153 Op->Bitfield.LSB = LSB;
2154 Op->Bitfield.Width = Width;
2155 Op->StartLoc = S;
2156 Op->EndLoc = E;
2157 return Op;
2158 }
2159
Bill Wendling2cae3272010-11-09 22:44:22 +00002160 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00002161 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002162 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002163 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002164
Jim Grosbach75461af2011-09-13 22:56:44 +00002165 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002166 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00002167 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00002168 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002169 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002170
2171 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00002172 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002173 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00002174 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00002175 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002176 Op->StartLoc = StartLoc;
2177 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00002178 return Op;
2179 }
2180
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002181 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach2f50e922011-12-15 21:44:33 +00002182 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002183 ARMOperand *Op = new ARMOperand(k_VectorList);
2184 Op->VectorList.RegNum = RegNum;
2185 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002186 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002187 Op->StartLoc = S;
2188 Op->EndLoc = E;
2189 return Op;
2190 }
2191
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002192 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002193 bool isDoubleSpaced,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002194 SMLoc S, SMLoc E) {
2195 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2196 Op->VectorList.RegNum = RegNum;
2197 Op->VectorList.Count = Count;
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002198 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002199 Op->StartLoc = S;
2200 Op->EndLoc = E;
2201 return Op;
2202 }
2203
Jim Grosbach04945c42011-12-02 00:35:16 +00002204 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002205 unsigned Index,
2206 bool isDoubleSpaced,
2207 SMLoc S, SMLoc E) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002208 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2209 Op->VectorList.RegNum = RegNum;
2210 Op->VectorList.Count = Count;
2211 Op->VectorList.LaneIndex = Index;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002212 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach04945c42011-12-02 00:35:16 +00002213 Op->StartLoc = S;
2214 Op->EndLoc = E;
2215 return Op;
2216 }
2217
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002218 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2219 MCContext &Ctx) {
2220 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2221 Op->VectorIndex.Val = Idx;
2222 Op->StartLoc = S;
2223 Op->EndLoc = E;
2224 return Op;
2225 }
2226
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002227 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002228 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002229 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002230 Op->StartLoc = S;
2231 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002232 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002233 }
2234
Jim Grosbachd3595712011-08-03 23:50:40 +00002235 static ARMOperand *CreateMem(unsigned BaseRegNum,
2236 const MCConstantExpr *OffsetImm,
2237 unsigned OffsetRegNum,
2238 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002239 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002240 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002241 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002242 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002243 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002244 Op->Memory.BaseRegNum = BaseRegNum;
2245 Op->Memory.OffsetImm = OffsetImm;
2246 Op->Memory.OffsetRegNum = OffsetRegNum;
2247 Op->Memory.ShiftType = ShiftType;
2248 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002249 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002250 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002251 Op->StartLoc = S;
2252 Op->EndLoc = E;
2253 return Op;
2254 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002255
Jim Grosbachc320c852011-08-05 21:28:30 +00002256 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2257 ARM_AM::ShiftOpc ShiftTy,
2258 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002259 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002260 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002261 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002262 Op->PostIdxReg.isAdd = isAdd;
2263 Op->PostIdxReg.ShiftTy = ShiftTy;
2264 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002265 Op->StartLoc = S;
2266 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002267 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002268 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002269
2270 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002271 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002272 Op->MBOpt.Val = Opt;
2273 Op->StartLoc = S;
2274 Op->EndLoc = S;
2275 return Op;
2276 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002277
2278 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002279 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002280 Op->IFlags.Val = IFlags;
2281 Op->StartLoc = S;
2282 Op->EndLoc = S;
2283 return Op;
2284 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002285
2286 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002287 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002288 Op->MMask.Val = MMask;
2289 Op->StartLoc = S;
2290 Op->EndLoc = S;
2291 return Op;
2292 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002293};
2294
2295} // end anonymous namespace.
2296
Jim Grosbach602aa902011-07-13 15:34:57 +00002297void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002298 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002299 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002300 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002301 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002302 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002303 OS << "<ccout " << getReg() << ">";
2304 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002305 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002306 static const char *MaskStr[] = {
2307 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2308 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2309 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002310 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2311 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2312 break;
2313 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002314 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002315 OS << "<coprocessor number: " << getCoproc() << ">";
2316 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002317 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002318 OS << "<coprocessor register: " << getCoproc() << ">";
2319 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002320 case k_CoprocOption:
2321 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2322 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002323 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002324 OS << "<mask: " << getMSRMask() << ">";
2325 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002326 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002327 getImm()->print(OS);
2328 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002329 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002330 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2331 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002332 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002333 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002334 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002335 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002336 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002337 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002338 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2339 << PostIdxReg.RegNum;
2340 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2341 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2342 << PostIdxReg.ShiftImm;
2343 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002344 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002345 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002346 OS << "<ARM_PROC::";
2347 unsigned IFlags = getProcIFlags();
2348 for (int i=2; i >= 0; --i)
2349 if (IFlags & (1 << i))
2350 OS << ARM_PROC::IFlagsToString(1 << i);
2351 OS << ">";
2352 break;
2353 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002354 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002355 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002356 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002357 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002358 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2359 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002360 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002361 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002362 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002363 << RegShiftedReg.SrcReg << " "
2364 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2365 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002366 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002367 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002368 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002369 << RegShiftedImm.SrcReg << " "
2370 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2371 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002372 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002373 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002374 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2375 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002376 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002377 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2378 << ", width: " << Bitfield.Width << ">";
2379 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002380 case k_RegisterList:
2381 case k_DPRRegisterList:
2382 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002383 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002384
Bill Wendlingbed94652010-11-09 23:28:44 +00002385 const SmallVectorImpl<unsigned> &RegList = getRegList();
2386 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002387 I = RegList.begin(), E = RegList.end(); I != E; ) {
2388 OS << *I;
2389 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002390 }
2391
2392 OS << ">";
2393 break;
2394 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002395 case k_VectorList:
2396 OS << "<vector_list " << VectorList.Count << " * "
2397 << VectorList.RegNum << ">";
2398 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002399 case k_VectorListAllLanes:
2400 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2401 << VectorList.RegNum << ">";
2402 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002403 case k_VectorListIndexed:
2404 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2405 << VectorList.Count << " * " << VectorList.RegNum << ">";
2406 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002407 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002408 OS << "'" << getToken() << "'";
2409 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002410 case k_VectorIndex:
2411 OS << "<vectorindex " << getVectorIndex() << ">";
2412 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002413 }
2414}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002415
2416/// @name Auto-generated Match Functions
2417/// {
2418
2419static unsigned MatchRegisterName(StringRef Name);
2420
2421/// }
2422
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002423bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2424 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002425 StartLoc = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002426 RegNo = tryParseRegister();
Jim Grosbachab5830e2011-12-14 02:16:11 +00002427 EndLoc = Parser.getTok().getLoc();
Roman Divacky36b1b472011-01-27 17:14:22 +00002428
2429 return (RegNo == (unsigned)-1);
2430}
2431
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002432/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002433/// and if it is a register name the token is eaten and the register number is
2434/// returned. Otherwise return -1.
2435///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002436int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002437 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002438 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002439
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002440 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002441 unsigned RegNum = MatchRegisterName(lowerCase);
2442 if (!RegNum) {
2443 RegNum = StringSwitch<unsigned>(lowerCase)
2444 .Case("r13", ARM::SP)
2445 .Case("r14", ARM::LR)
2446 .Case("r15", ARM::PC)
2447 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002448 // Additional register name aliases for 'gas' compatibility.
2449 .Case("a1", ARM::R0)
2450 .Case("a2", ARM::R1)
2451 .Case("a3", ARM::R2)
2452 .Case("a4", ARM::R3)
2453 .Case("v1", ARM::R4)
2454 .Case("v2", ARM::R5)
2455 .Case("v3", ARM::R6)
2456 .Case("v4", ARM::R7)
2457 .Case("v5", ARM::R8)
2458 .Case("v6", ARM::R9)
2459 .Case("v7", ARM::R10)
2460 .Case("v8", ARM::R11)
2461 .Case("sb", ARM::R9)
2462 .Case("sl", ARM::R10)
2463 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002464 .Default(0);
2465 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002466 if (!RegNum) {
Jim Grosbachcd22e4a2011-12-20 23:11:00 +00002467 // Check for aliases registered via .req. Canonicalize to lower case.
2468 // That's more consistent since register names are case insensitive, and
2469 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2470 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbachab5830e2011-12-14 02:16:11 +00002471 // If no match, return failure.
2472 if (Entry == RegisterReqs.end())
2473 return -1;
2474 Parser.Lex(); // Eat identifier token.
2475 return Entry->getValue();
2476 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002477
Chris Lattner44e5981c2010-10-30 04:09:10 +00002478 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002479
Chris Lattner44e5981c2010-10-30 04:09:10 +00002480 return RegNum;
2481}
Jim Grosbach99710a82010-11-01 16:44:21 +00002482
Jim Grosbachbb24c592011-07-13 18:49:30 +00002483// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2484// If a recoverable error occurs, return 1. If an irrecoverable error
2485// occurs, return -1. An irrecoverable error is one where tokens have been
2486// consumed in the process of trying to parse the shifter (i.e., when it is
2487// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002488int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002489 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2490 SMLoc S = Parser.getTok().getLoc();
2491 const AsmToken &Tok = Parser.getTok();
2492 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2493
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002494 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002495 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002496 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002497 .Case("lsl", ARM_AM::lsl)
2498 .Case("lsr", ARM_AM::lsr)
2499 .Case("asr", ARM_AM::asr)
2500 .Case("ror", ARM_AM::ror)
2501 .Case("rrx", ARM_AM::rrx)
2502 .Default(ARM_AM::no_shift);
2503
2504 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002505 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002506
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002507 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002508
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002509 // The source register for the shift has already been added to the
2510 // operand list, so we need to pop it off and combine it into the shifted
2511 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002512 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002513 if (!PrevOp->isReg())
2514 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2515 int SrcReg = PrevOp->getReg();
2516 int64_t Imm = 0;
2517 int ShiftReg = 0;
2518 if (ShiftTy == ARM_AM::rrx) {
2519 // RRX Doesn't have an explicit shift amount. The encoder expects
2520 // the shift register to be the same as the source register. Seems odd,
2521 // but OK.
2522 ShiftReg = SrcReg;
2523 } else {
2524 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002525 if (Parser.getTok().is(AsmToken::Hash) ||
2526 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002527 Parser.Lex(); // Eat hash.
2528 SMLoc ImmLoc = Parser.getTok().getLoc();
2529 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002530 if (getParser().ParseExpression(ShiftExpr)) {
2531 Error(ImmLoc, "invalid immediate shift value");
2532 return -1;
2533 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002534 // The expression must be evaluatable as an immediate.
2535 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002536 if (!CE) {
2537 Error(ImmLoc, "invalid immediate shift value");
2538 return -1;
2539 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002540 // Range check the immediate.
2541 // lsl, ror: 0 <= imm <= 31
2542 // lsr, asr: 0 <= imm <= 32
2543 Imm = CE->getValue();
2544 if (Imm < 0 ||
2545 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2546 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002547 Error(ImmLoc, "immediate shift value out of range");
2548 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002549 }
Jim Grosbach21488b82011-12-22 17:37:00 +00002550 // shift by zero is a nop. Always send it through as lsl.
2551 // ('as' compatibility)
2552 if (Imm == 0)
2553 ShiftTy = ARM_AM::lsl;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002554 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002555 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002556 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002557 if (ShiftReg == -1) {
2558 Error (L, "expected immediate or register in shift operand");
2559 return -1;
2560 }
2561 } else {
2562 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002563 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002564 return -1;
2565 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002566 }
2567
Owen Andersonb595ed02011-07-21 18:54:16 +00002568 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2569 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002570 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002571 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002572 else
2573 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2574 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002575
Jim Grosbachbb24c592011-07-13 18:49:30 +00002576 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002577}
2578
2579
Bill Wendling2063b842010-11-18 23:43:05 +00002580/// Try to parse a register name. The token must be an Identifier when called.
2581/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2582/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002583///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002584/// TODO this is likely to change to allow different register types and or to
2585/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002586bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002587tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002588 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002589 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002590 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002591 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002592
Bill Wendling2063b842010-11-18 23:43:05 +00002593 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002594
Chris Lattner44e5981c2010-10-30 04:09:10 +00002595 const AsmToken &ExclaimTok = Parser.getTok();
2596 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002597 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2598 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002599 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002600 return false;
2601 }
2602
2603 // Also check for an index operand. This is only legal for vector registers,
2604 // but that'll get caught OK in operand matching, so we don't need to
2605 // explicitly filter everything else out here.
2606 if (Parser.getTok().is(AsmToken::LBrac)) {
2607 SMLoc SIdx = Parser.getTok().getLoc();
2608 Parser.Lex(); // Eat left bracket token.
2609
2610 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002611 if (getParser().ParseExpression(ImmVal))
Jim Grosbacha2147ce2012-01-31 23:51:09 +00002612 return true;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002613 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachc8f2b782012-01-26 15:56:45 +00002614 if (!MCE)
2615 return TokError("immediate value expected for vector index");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002616
2617 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachc8f2b782012-01-26 15:56:45 +00002618 if (Parser.getTok().isNot(AsmToken::RBrac))
2619 return Error(E, "']' expected");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002620
2621 Parser.Lex(); // Eat right bracket token.
2622
2623 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2624 SIdx, E,
2625 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002626 }
2627
Bill Wendling2063b842010-11-18 23:43:05 +00002628 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002629}
2630
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002631/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2632/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2633/// "c5", ...
2634static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002635 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2636 // but efficient.
2637 switch (Name.size()) {
David Blaikie46a9f012012-01-20 21:51:11 +00002638 default: return -1;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002639 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002640 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002641 return -1;
2642 switch (Name[1]) {
2643 default: return -1;
2644 case '0': return 0;
2645 case '1': return 1;
2646 case '2': return 2;
2647 case '3': return 3;
2648 case '4': return 4;
2649 case '5': return 5;
2650 case '6': return 6;
2651 case '7': return 7;
2652 case '8': return 8;
2653 case '9': return 9;
2654 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002655 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002656 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002657 return -1;
2658 switch (Name[2]) {
2659 default: return -1;
2660 case '0': return 10;
2661 case '1': return 11;
2662 case '2': return 12;
2663 case '3': return 13;
2664 case '4': return 14;
2665 case '5': return 15;
2666 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002667 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002668}
2669
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002670/// parseITCondCode - Try to parse a condition code for an IT instruction.
2671ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2672parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2673 SMLoc S = Parser.getTok().getLoc();
2674 const AsmToken &Tok = Parser.getTok();
2675 if (!Tok.is(AsmToken::Identifier))
2676 return MatchOperand_NoMatch;
Richard Barton82f95ea2012-04-27 17:34:01 +00002677 unsigned CC = StringSwitch<unsigned>(Tok.getString().lower())
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002678 .Case("eq", ARMCC::EQ)
2679 .Case("ne", ARMCC::NE)
2680 .Case("hs", ARMCC::HS)
2681 .Case("cs", ARMCC::HS)
2682 .Case("lo", ARMCC::LO)
2683 .Case("cc", ARMCC::LO)
2684 .Case("mi", ARMCC::MI)
2685 .Case("pl", ARMCC::PL)
2686 .Case("vs", ARMCC::VS)
2687 .Case("vc", ARMCC::VC)
2688 .Case("hi", ARMCC::HI)
2689 .Case("ls", ARMCC::LS)
2690 .Case("ge", ARMCC::GE)
2691 .Case("lt", ARMCC::LT)
2692 .Case("gt", ARMCC::GT)
2693 .Case("le", ARMCC::LE)
2694 .Case("al", ARMCC::AL)
2695 .Default(~0U);
2696 if (CC == ~0U)
2697 return MatchOperand_NoMatch;
2698 Parser.Lex(); // Eat the token.
2699
2700 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2701
2702 return MatchOperand_Success;
2703}
2704
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002705/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002706/// token must be an Identifier when called, and if it is a coprocessor
2707/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002708ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002709parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002710 SMLoc S = Parser.getTok().getLoc();
2711 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002712 if (Tok.isNot(AsmToken::Identifier))
2713 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002714
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002715 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002716 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002717 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002718
2719 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002720 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002721 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002722}
2723
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002724/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002725/// token must be an Identifier when called, and if it is a coprocessor
2726/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002727ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002728parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002729 SMLoc S = Parser.getTok().getLoc();
2730 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002731 if (Tok.isNot(AsmToken::Identifier))
2732 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002733
2734 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2735 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002736 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002737
2738 Parser.Lex(); // Eat identifier token.
2739 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002740 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002741}
2742
Jim Grosbach48399582011-10-12 17:34:41 +00002743/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2744/// coproc_option : '{' imm0_255 '}'
2745ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2746parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2747 SMLoc S = Parser.getTok().getLoc();
2748
2749 // If this isn't a '{', this isn't a coprocessor immediate operand.
2750 if (Parser.getTok().isNot(AsmToken::LCurly))
2751 return MatchOperand_NoMatch;
2752 Parser.Lex(); // Eat the '{'
2753
2754 const MCExpr *Expr;
2755 SMLoc Loc = Parser.getTok().getLoc();
2756 if (getParser().ParseExpression(Expr)) {
2757 Error(Loc, "illegal expression");
2758 return MatchOperand_ParseFail;
2759 }
2760 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2761 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2762 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2763 return MatchOperand_ParseFail;
2764 }
2765 int Val = CE->getValue();
2766
2767 // Check for and consume the closing '}'
2768 if (Parser.getTok().isNot(AsmToken::RCurly))
2769 return MatchOperand_ParseFail;
2770 SMLoc E = Parser.getTok().getLoc();
2771 Parser.Lex(); // Eat the '}'
2772
2773 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2774 return MatchOperand_Success;
2775}
2776
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002777// For register list parsing, we need to map from raw GPR register numbering
2778// to the enumeration values. The enumeration values aren't sorted by
2779// register number due to our using "sp", "lr" and "pc" as canonical names.
2780static unsigned getNextRegister(unsigned Reg) {
2781 // If this is a GPR, we need to do it manually, otherwise we can rely
2782 // on the sort ordering of the enumeration since the other reg-classes
2783 // are sane.
2784 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2785 return Reg + 1;
2786 switch(Reg) {
Craig Toppere55c5562012-02-07 02:50:20 +00002787 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002788 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2789 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2790 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2791 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2792 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2793 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2794 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2795 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2796 }
2797}
2798
Jim Grosbach85a23432011-11-11 21:27:40 +00002799// Return the low-subreg of a given Q register.
2800static unsigned getDRegFromQReg(unsigned QReg) {
2801 switch (QReg) {
2802 default: llvm_unreachable("expected a Q register!");
2803 case ARM::Q0: return ARM::D0;
2804 case ARM::Q1: return ARM::D2;
2805 case ARM::Q2: return ARM::D4;
2806 case ARM::Q3: return ARM::D6;
2807 case ARM::Q4: return ARM::D8;
2808 case ARM::Q5: return ARM::D10;
2809 case ARM::Q6: return ARM::D12;
2810 case ARM::Q7: return ARM::D14;
2811 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002812 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002813 case ARM::Q10: return ARM::D20;
2814 case ARM::Q11: return ARM::D22;
2815 case ARM::Q12: return ARM::D24;
2816 case ARM::Q13: return ARM::D26;
2817 case ARM::Q14: return ARM::D28;
2818 case ARM::Q15: return ARM::D30;
2819 }
2820}
2821
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002822/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002823bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002824parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002825 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002826 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002827 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002828 Parser.Lex(); // Eat '{' token.
2829 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002830
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002831 // Check the first register in the list to see what register class
2832 // this is a list of.
2833 int Reg = tryParseRegister();
2834 if (Reg == -1)
2835 return Error(RegLoc, "register expected");
2836
Jim Grosbach85a23432011-11-11 21:27:40 +00002837 // The reglist instructions have at most 16 registers, so reserve
2838 // space for that many.
2839 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2840
2841 // Allow Q regs and just interpret them as the two D sub-registers.
2842 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2843 Reg = getDRegFromQReg(Reg);
2844 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2845 ++Reg;
2846 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002847 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002848 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2849 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2850 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2851 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2852 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2853 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2854 else
2855 return Error(RegLoc, "invalid register in register list");
2856
Jim Grosbach85a23432011-11-11 21:27:40 +00002857 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002858 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002859
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002860 // This starts immediately after the first register token in the list,
2861 // so we can see either a comma or a minus (range separator) as a legal
2862 // next token.
2863 while (Parser.getTok().is(AsmToken::Comma) ||
2864 Parser.getTok().is(AsmToken::Minus)) {
2865 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002866 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002867 SMLoc EndLoc = Parser.getTok().getLoc();
2868 int EndReg = tryParseRegister();
2869 if (EndReg == -1)
2870 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002871 // Allow Q regs and just interpret them as the two D sub-registers.
2872 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2873 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002874 // If the register is the same as the start reg, there's nothing
2875 // more to do.
2876 if (Reg == EndReg)
2877 continue;
2878 // The register must be in the same register class as the first.
2879 if (!RC->contains(EndReg))
2880 return Error(EndLoc, "invalid register in register list");
2881 // Ranges must go from low to high.
2882 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2883 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002884
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002885 // Add all the registers in the range to the register list.
2886 while (Reg != EndReg) {
2887 Reg = getNextRegister(Reg);
2888 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2889 }
2890 continue;
2891 }
2892 Parser.Lex(); // Eat the comma.
2893 RegLoc = Parser.getTok().getLoc();
2894 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002895 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002896 Reg = tryParseRegister();
2897 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002898 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002899 // Allow Q regs and just interpret them as the two D sub-registers.
2900 bool isQReg = false;
2901 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2902 Reg = getDRegFromQReg(Reg);
2903 isQReg = true;
2904 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002905 // The register must be in the same register class as the first.
2906 if (!RC->contains(Reg))
2907 return Error(RegLoc, "invalid register in register list");
2908 // List must be monotonically increasing.
Jim Grosbach905686a2012-03-16 20:48:38 +00002909 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2910 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2911 Warning(RegLoc, "register list not in ascending order");
2912 else
2913 return Error(RegLoc, "register list not in ascending order");
2914 }
Jim Grosbach98bc7972011-12-08 21:34:20 +00002915 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2916 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2917 ") in register list");
2918 continue;
2919 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002920 // VFP register lists must also be contiguous.
2921 // It's OK to use the enumeration values directly here rather, as the
2922 // VFP register classes have the enum sorted properly.
2923 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2924 Reg != OldReg + 1)
2925 return Error(RegLoc, "non-contiguous register range");
2926 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002927 if (isQReg)
2928 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002929 }
2930
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002931 SMLoc E = Parser.getTok().getLoc();
2932 if (Parser.getTok().isNot(AsmToken::RCurly))
2933 return Error(E, "'}' expected");
2934 Parser.Lex(); // Eat '}' token.
2935
Jim Grosbach18bf3632011-12-13 21:48:29 +00002936 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002937 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002938
2939 // The ARM system instruction variants for LDM/STM have a '^' token here.
2940 if (Parser.getTok().is(AsmToken::Caret)) {
2941 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2942 Parser.Lex(); // Eat '^' token.
2943 }
2944
Bill Wendling2063b842010-11-18 23:43:05 +00002945 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002946}
2947
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002948// Helper function to parse the lane index for vector lists.
2949ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002950parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2951 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002952 if (Parser.getTok().is(AsmToken::LBrac)) {
2953 Parser.Lex(); // Eat the '['.
2954 if (Parser.getTok().is(AsmToken::RBrac)) {
2955 // "Dn[]" is the 'all lanes' syntax.
2956 LaneKind = AllLanes;
2957 Parser.Lex(); // Eat the ']'.
2958 return MatchOperand_Success;
2959 }
Jim Grosbach67e76ba2012-03-19 20:39:53 +00002960
2961 // There's an optional '#' token here. Normally there wouldn't be, but
2962 // inline assemble puts one in, and it's friendly to accept that.
2963 if (Parser.getTok().is(AsmToken::Hash))
2964 Parser.Lex(); // Eat the '#'
2965
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002966 const MCExpr *LaneIndex;
2967 SMLoc Loc = Parser.getTok().getLoc();
2968 if (getParser().ParseExpression(LaneIndex)) {
2969 Error(Loc, "illegal expression");
2970 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002971 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002972 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2973 if (!CE) {
2974 Error(Loc, "lane index must be empty or an integer");
2975 return MatchOperand_ParseFail;
2976 }
2977 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2978 Error(Parser.getTok().getLoc(), "']' expected");
2979 return MatchOperand_ParseFail;
2980 }
2981 Parser.Lex(); // Eat the ']'.
2982 int64_t Val = CE->getValue();
2983
2984 // FIXME: Make this range check context sensitive for .8, .16, .32.
2985 if (Val < 0 || Val > 7) {
2986 Error(Parser.getTok().getLoc(), "lane index out of range");
2987 return MatchOperand_ParseFail;
2988 }
2989 Index = Val;
2990 LaneKind = IndexedLane;
2991 return MatchOperand_Success;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002992 }
2993 LaneKind = NoLanes;
2994 return MatchOperand_Success;
2995}
2996
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002997// parse a vector register list
2998ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2999parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003000 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003001 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00003002 SMLoc S = Parser.getTok().getLoc();
3003 // As an extension (to match gas), support a plain D register or Q register
3004 // (without encosing curly braces) as a single or double entry list,
3005 // respectively.
3006 if (Parser.getTok().is(AsmToken::Identifier)) {
3007 int Reg = tryParseRegister();
3008 if (Reg == -1)
3009 return MatchOperand_NoMatch;
3010 SMLoc E = Parser.getTok().getLoc();
3011 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00003012 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003013 if (Res != MatchOperand_Success)
3014 return Res;
3015 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003016 case NoLanes:
3017 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00003018 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003019 break;
3020 case AllLanes:
3021 E = Parser.getTok().getLoc();
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003022 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3023 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003024 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003025 case IndexedLane:
3026 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003027 LaneIndex,
3028 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003029 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003030 }
Jim Grosbach8d579232011-11-15 21:45:55 +00003031 return MatchOperand_Success;
3032 }
3033 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3034 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00003035 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003036 if (Res != MatchOperand_Success)
3037 return Res;
3038 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003039 case NoLanes:
3040 E = Parser.getTok().getLoc();
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003041 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbach13a292c2012-03-06 22:01:44 +00003042 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach2f50e922011-12-15 21:44:33 +00003043 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003044 break;
3045 case AllLanes:
3046 E = Parser.getTok().getLoc();
Jim Grosbach13a292c2012-03-06 22:01:44 +00003047 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3048 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003049 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3050 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003051 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003052 case IndexedLane:
3053 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003054 LaneIndex,
3055 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003056 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003057 }
Jim Grosbach8d579232011-11-15 21:45:55 +00003058 return MatchOperand_Success;
3059 }
3060 Error(S, "vector register expected");
3061 return MatchOperand_ParseFail;
3062 }
3063
3064 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003065 return MatchOperand_NoMatch;
3066
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003067 Parser.Lex(); // Eat '{' token.
3068 SMLoc RegLoc = Parser.getTok().getLoc();
3069
3070 int Reg = tryParseRegister();
3071 if (Reg == -1) {
3072 Error(RegLoc, "register expected");
3073 return MatchOperand_ParseFail;
3074 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003075 unsigned Count = 1;
Jim Grosbachc2f16a32011-12-15 21:54:55 +00003076 int Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00003077 unsigned FirstReg = Reg;
3078 // The list is of D registers, but we also allow Q regs and just interpret
3079 // them as the two D sub-registers.
3080 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3081 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00003082 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3083 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00003084 ++Reg;
3085 ++Count;
3086 }
Jim Grosbach04945c42011-12-02 00:35:16 +00003087 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003088 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00003089
Jim Grosbache891fe82011-11-15 23:19:15 +00003090 while (Parser.getTok().is(AsmToken::Comma) ||
3091 Parser.getTok().is(AsmToken::Minus)) {
3092 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003093 if (!Spacing)
3094 Spacing = 1; // Register range implies a single spaced list.
3095 else if (Spacing == 2) {
3096 Error(Parser.getTok().getLoc(),
3097 "sequential registers in double spaced list");
3098 return MatchOperand_ParseFail;
3099 }
Jim Grosbache891fe82011-11-15 23:19:15 +00003100 Parser.Lex(); // Eat the minus.
3101 SMLoc EndLoc = Parser.getTok().getLoc();
3102 int EndReg = tryParseRegister();
3103 if (EndReg == -1) {
3104 Error(EndLoc, "register expected");
3105 return MatchOperand_ParseFail;
3106 }
3107 // Allow Q regs and just interpret them as the two D sub-registers.
3108 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3109 EndReg = getDRegFromQReg(EndReg) + 1;
3110 // If the register is the same as the start reg, there's nothing
3111 // more to do.
3112 if (Reg == EndReg)
3113 continue;
3114 // The register must be in the same register class as the first.
3115 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3116 Error(EndLoc, "invalid register in register list");
3117 return MatchOperand_ParseFail;
3118 }
3119 // Ranges must go from low to high.
3120 if (Reg > EndReg) {
3121 Error(EndLoc, "bad range in register list");
3122 return MatchOperand_ParseFail;
3123 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003124 // Parse the lane specifier if present.
3125 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003126 unsigned NextLaneIndex;
3127 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003128 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003129 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003130 Error(EndLoc, "mismatched lane index in register list");
3131 return MatchOperand_ParseFail;
3132 }
3133 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00003134
3135 // Add all the registers in the range to the register list.
3136 Count += EndReg - Reg;
3137 Reg = EndReg;
3138 continue;
3139 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003140 Parser.Lex(); // Eat the comma.
3141 RegLoc = Parser.getTok().getLoc();
3142 int OldReg = Reg;
3143 Reg = tryParseRegister();
3144 if (Reg == -1) {
3145 Error(RegLoc, "register expected");
3146 return MatchOperand_ParseFail;
3147 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003148 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003149 // It's OK to use the enumeration values directly here rather, as the
3150 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00003151 //
3152 // The list is of D registers, but we also allow Q regs and just interpret
3153 // them as the two D sub-registers.
3154 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003155 if (!Spacing)
3156 Spacing = 1; // Register range implies a single spaced list.
3157 else if (Spacing == 2) {
3158 Error(RegLoc,
3159 "invalid register in double-spaced list (must be 'D' register')");
3160 return MatchOperand_ParseFail;
3161 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003162 Reg = getDRegFromQReg(Reg);
3163 if (Reg != OldReg + 1) {
3164 Error(RegLoc, "non-contiguous register range");
3165 return MatchOperand_ParseFail;
3166 }
3167 ++Reg;
3168 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003169 // Parse the lane specifier if present.
3170 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003171 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003172 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003173 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003174 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003175 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003176 Error(EndLoc, "mismatched lane index in register list");
3177 return MatchOperand_ParseFail;
3178 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003179 continue;
3180 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00003181 // Normal D register.
3182 // Figure out the register spacing (single or double) of the list if
3183 // we don't know it already.
3184 if (!Spacing)
3185 Spacing = 1 + (Reg == OldReg + 2);
3186
3187 // Just check that it's contiguous and keep going.
3188 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003189 Error(RegLoc, "non-contiguous register range");
3190 return MatchOperand_ParseFail;
3191 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003192 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003193 // Parse the lane specifier if present.
3194 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003195 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003196 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003197 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003198 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003199 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003200 Error(EndLoc, "mismatched lane index in register list");
3201 return MatchOperand_ParseFail;
3202 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003203 }
3204
3205 SMLoc E = Parser.getTok().getLoc();
3206 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3207 Error(E, "'}' expected");
3208 return MatchOperand_ParseFail;
3209 }
3210 Parser.Lex(); // Eat '}' token.
3211
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003212 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003213 case NoLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003214 // Two-register operands have been converted to the
Jim Grosbache5307f92012-03-05 21:43:40 +00003215 // composite register classes.
3216 if (Count == 2) {
3217 const MCRegisterClass *RC = (Spacing == 1) ?
3218 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3219 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3220 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3221 }
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003222
Jim Grosbach2f50e922011-12-15 21:44:33 +00003223 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3224 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003225 break;
3226 case AllLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003227 // Two-register operands have been converted to the
3228 // composite register classes.
Jim Grosbached428bc2012-03-06 23:10:38 +00003229 if (Count == 2) {
3230 const MCRegisterClass *RC = (Spacing == 1) ?
3231 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3232 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbach13a292c2012-03-06 22:01:44 +00003233 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3234 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003235 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003236 (Spacing == 2),
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003237 S, E));
3238 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003239 case IndexedLane:
3240 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003241 LaneIndex,
3242 (Spacing == 2),
3243 S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003244 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003245 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003246 return MatchOperand_Success;
3247}
3248
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003249/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003250ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003251parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003252 SMLoc S = Parser.getTok().getLoc();
3253 const AsmToken &Tok = Parser.getTok();
3254 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3255 StringRef OptStr = Tok.getString();
3256
3257 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3258 .Case("sy", ARM_MB::SY)
3259 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003260 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003261 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003262 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003263 .Case("ishst", ARM_MB::ISHST)
3264 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003265 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003266 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003267 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003268 .Case("osh", ARM_MB::OSH)
3269 .Case("oshst", ARM_MB::OSHST)
3270 .Default(~0U);
3271
3272 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003273 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003274
3275 Parser.Lex(); // Eat identifier token.
3276 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003277 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003278}
3279
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003280/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003281ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003282parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003283 SMLoc S = Parser.getTok().getLoc();
3284 const AsmToken &Tok = Parser.getTok();
3285 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3286 StringRef IFlagsStr = Tok.getString();
3287
Owen Anderson10c5b122011-10-05 17:16:40 +00003288 // An iflags string of "none" is interpreted to mean that none of the AIF
3289 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003290 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003291 if (IFlagsStr != "none") {
3292 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3293 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3294 .Case("a", ARM_PROC::A)
3295 .Case("i", ARM_PROC::I)
3296 .Case("f", ARM_PROC::F)
3297 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003298
Owen Anderson10c5b122011-10-05 17:16:40 +00003299 // If some specific iflag is already set, it means that some letter is
3300 // present more than once, this is not acceptable.
3301 if (Flag == ~0U || (IFlags & Flag))
3302 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003303
Owen Anderson10c5b122011-10-05 17:16:40 +00003304 IFlags |= Flag;
3305 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003306 }
3307
3308 Parser.Lex(); // Eat identifier token.
3309 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3310 return MatchOperand_Success;
3311}
3312
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003313/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003314ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003315parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003316 SMLoc S = Parser.getTok().getLoc();
3317 const AsmToken &Tok = Parser.getTok();
3318 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3319 StringRef Mask = Tok.getString();
3320
James Molloy21efa7d2011-09-28 14:21:38 +00003321 if (isMClass()) {
3322 // See ARMv6-M 10.1.1
Jim Grosbachd28888d2012-03-15 21:34:14 +00003323 std::string Name = Mask.lower();
3324 unsigned FlagsVal = StringSwitch<unsigned>(Name)
James Molloy21efa7d2011-09-28 14:21:38 +00003325 .Case("apsr", 0)
3326 .Case("iapsr", 1)
3327 .Case("eapsr", 2)
3328 .Case("xpsr", 3)
3329 .Case("ipsr", 5)
3330 .Case("epsr", 6)
3331 .Case("iepsr", 7)
3332 .Case("msp", 8)
3333 .Case("psp", 9)
3334 .Case("primask", 16)
3335 .Case("basepri", 17)
3336 .Case("basepri_max", 18)
3337 .Case("faultmask", 19)
3338 .Case("control", 20)
3339 .Default(~0U);
Jim Grosbach3794d822011-12-22 17:17:10 +00003340
James Molloy21efa7d2011-09-28 14:21:38 +00003341 if (FlagsVal == ~0U)
3342 return MatchOperand_NoMatch;
3343
3344 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3345 // basepri, basepri_max and faultmask only valid for V7m.
3346 return MatchOperand_NoMatch;
Jim Grosbach3794d822011-12-22 17:17:10 +00003347
James Molloy21efa7d2011-09-28 14:21:38 +00003348 Parser.Lex(); // Eat identifier token.
3349 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3350 return MatchOperand_Success;
3351 }
3352
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003353 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3354 size_t Start = 0, Next = Mask.find('_');
3355 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003356 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003357 if (Next != StringRef::npos)
3358 Flags = Mask.slice(Next+1, Mask.size());
3359
3360 // FlagsVal contains the complete mask:
3361 // 3-0: Mask
3362 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3363 unsigned FlagsVal = 0;
3364
3365 if (SpecReg == "apsr") {
3366 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003367 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003368 .Case("g", 0x4) // same as CPSR_s
3369 .Case("nzcvqg", 0xc) // same as CPSR_fs
3370 .Default(~0U);
3371
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003372 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003373 if (!Flags.empty())
3374 return MatchOperand_NoMatch;
3375 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003376 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003377 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003378 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Jim Grosbach3d00eec2012-04-05 03:17:53 +00003379 // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
3380 if (Flags == "all" || Flags == "")
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003381 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003382 for (int i = 0, e = Flags.size(); i != e; ++i) {
3383 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3384 .Case("c", 1)
3385 .Case("x", 2)
3386 .Case("s", 4)
3387 .Case("f", 8)
3388 .Default(~0U);
3389
3390 // If some specific flag is already set, it means that some letter is
3391 // present more than once, this is not acceptable.
3392 if (FlagsVal == ~0U || (FlagsVal & Flag))
3393 return MatchOperand_NoMatch;
3394 FlagsVal |= Flag;
3395 }
3396 } else // No match for special register.
3397 return MatchOperand_NoMatch;
3398
Owen Anderson03a173e2011-10-21 18:43:28 +00003399 // Special register without flags is NOT equivalent to "fc" flags.
3400 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3401 // two lines would enable gas compatibility at the expense of breaking
3402 // round-tripping.
3403 //
3404 // if (!FlagsVal)
3405 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003406
3407 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3408 if (SpecReg == "spsr")
3409 FlagsVal |= 16;
3410
3411 Parser.Lex(); // Eat identifier token.
3412 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3413 return MatchOperand_Success;
3414}
3415
Jim Grosbach27c1e252011-07-21 17:23:04 +00003416ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3417parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3418 int Low, int High) {
3419 const AsmToken &Tok = Parser.getTok();
3420 if (Tok.isNot(AsmToken::Identifier)) {
3421 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3422 return MatchOperand_ParseFail;
3423 }
3424 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003425 std::string LowerOp = Op.lower();
3426 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003427 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3428 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3429 return MatchOperand_ParseFail;
3430 }
3431 Parser.Lex(); // Eat shift type token.
3432
3433 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003434 if (Parser.getTok().isNot(AsmToken::Hash) &&
3435 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003436 Error(Parser.getTok().getLoc(), "'#' expected");
3437 return MatchOperand_ParseFail;
3438 }
3439 Parser.Lex(); // Eat hash token.
3440
3441 const MCExpr *ShiftAmount;
3442 SMLoc Loc = Parser.getTok().getLoc();
3443 if (getParser().ParseExpression(ShiftAmount)) {
3444 Error(Loc, "illegal expression");
3445 return MatchOperand_ParseFail;
3446 }
3447 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3448 if (!CE) {
3449 Error(Loc, "constant expression expected");
3450 return MatchOperand_ParseFail;
3451 }
3452 int Val = CE->getValue();
3453 if (Val < Low || Val > High) {
3454 Error(Loc, "immediate value out of range");
3455 return MatchOperand_ParseFail;
3456 }
3457
3458 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3459
3460 return MatchOperand_Success;
3461}
3462
Jim Grosbach0a547702011-07-22 17:44:50 +00003463ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3464parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3465 const AsmToken &Tok = Parser.getTok();
3466 SMLoc S = Tok.getLoc();
3467 if (Tok.isNot(AsmToken::Identifier)) {
3468 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3469 return MatchOperand_ParseFail;
3470 }
3471 int Val = StringSwitch<int>(Tok.getString())
3472 .Case("be", 1)
3473 .Case("le", 0)
3474 .Default(-1);
3475 Parser.Lex(); // Eat the token.
3476
3477 if (Val == -1) {
3478 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3479 return MatchOperand_ParseFail;
3480 }
3481 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3482 getContext()),
3483 S, Parser.getTok().getLoc()));
3484 return MatchOperand_Success;
3485}
3486
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003487/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3488/// instructions. Legal values are:
3489/// lsl #n 'n' in [0,31]
3490/// asr #n 'n' in [1,32]
3491/// n == 32 encoded as n == 0.
3492ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3493parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3494 const AsmToken &Tok = Parser.getTok();
3495 SMLoc S = Tok.getLoc();
3496 if (Tok.isNot(AsmToken::Identifier)) {
3497 Error(S, "shift operator 'asr' or 'lsl' expected");
3498 return MatchOperand_ParseFail;
3499 }
3500 StringRef ShiftName = Tok.getString();
3501 bool isASR;
3502 if (ShiftName == "lsl" || ShiftName == "LSL")
3503 isASR = false;
3504 else if (ShiftName == "asr" || ShiftName == "ASR")
3505 isASR = true;
3506 else {
3507 Error(S, "shift operator 'asr' or 'lsl' expected");
3508 return MatchOperand_ParseFail;
3509 }
3510 Parser.Lex(); // Eat the operator.
3511
3512 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003513 if (Parser.getTok().isNot(AsmToken::Hash) &&
3514 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003515 Error(Parser.getTok().getLoc(), "'#' expected");
3516 return MatchOperand_ParseFail;
3517 }
3518 Parser.Lex(); // Eat hash token.
3519
3520 const MCExpr *ShiftAmount;
3521 SMLoc E = Parser.getTok().getLoc();
3522 if (getParser().ParseExpression(ShiftAmount)) {
3523 Error(E, "malformed shift expression");
3524 return MatchOperand_ParseFail;
3525 }
3526 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3527 if (!CE) {
3528 Error(E, "shift amount must be an immediate");
3529 return MatchOperand_ParseFail;
3530 }
3531
3532 int64_t Val = CE->getValue();
3533 if (isASR) {
3534 // Shift amount must be in [1,32]
3535 if (Val < 1 || Val > 32) {
3536 Error(E, "'asr' shift amount must be in range [1,32]");
3537 return MatchOperand_ParseFail;
3538 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003539 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3540 if (isThumb() && Val == 32) {
3541 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3542 return MatchOperand_ParseFail;
3543 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003544 if (Val == 32) Val = 0;
3545 } else {
3546 // Shift amount must be in [1,32]
3547 if (Val < 0 || Val > 31) {
3548 Error(E, "'lsr' shift amount must be in range [0,31]");
3549 return MatchOperand_ParseFail;
3550 }
3551 }
3552
3553 E = Parser.getTok().getLoc();
3554 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3555
3556 return MatchOperand_Success;
3557}
3558
Jim Grosbach833b9d32011-07-27 20:15:40 +00003559/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3560/// of instructions. Legal values are:
3561/// ror #n 'n' in {0, 8, 16, 24}
3562ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3563parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3564 const AsmToken &Tok = Parser.getTok();
3565 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003566 if (Tok.isNot(AsmToken::Identifier))
3567 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003568 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003569 if (ShiftName != "ror" && ShiftName != "ROR")
3570 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003571 Parser.Lex(); // Eat the operator.
3572
3573 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003574 if (Parser.getTok().isNot(AsmToken::Hash) &&
3575 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003576 Error(Parser.getTok().getLoc(), "'#' expected");
3577 return MatchOperand_ParseFail;
3578 }
3579 Parser.Lex(); // Eat hash token.
3580
3581 const MCExpr *ShiftAmount;
3582 SMLoc E = Parser.getTok().getLoc();
3583 if (getParser().ParseExpression(ShiftAmount)) {
3584 Error(E, "malformed rotate expression");
3585 return MatchOperand_ParseFail;
3586 }
3587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3588 if (!CE) {
3589 Error(E, "rotate amount must be an immediate");
3590 return MatchOperand_ParseFail;
3591 }
3592
3593 int64_t Val = CE->getValue();
3594 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3595 // normally, zero is represented in asm by omitting the rotate operand
3596 // entirely.
3597 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3598 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3599 return MatchOperand_ParseFail;
3600 }
3601
3602 E = Parser.getTok().getLoc();
3603 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3604
3605 return MatchOperand_Success;
3606}
3607
Jim Grosbach864b6092011-07-28 21:34:26 +00003608ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3609parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3610 SMLoc S = Parser.getTok().getLoc();
3611 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003612 if (Parser.getTok().isNot(AsmToken::Hash) &&
3613 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003614 Error(Parser.getTok().getLoc(), "'#' expected");
3615 return MatchOperand_ParseFail;
3616 }
3617 Parser.Lex(); // Eat hash token.
3618
3619 const MCExpr *LSBExpr;
3620 SMLoc E = Parser.getTok().getLoc();
3621 if (getParser().ParseExpression(LSBExpr)) {
3622 Error(E, "malformed immediate expression");
3623 return MatchOperand_ParseFail;
3624 }
3625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3626 if (!CE) {
3627 Error(E, "'lsb' operand must be an immediate");
3628 return MatchOperand_ParseFail;
3629 }
3630
3631 int64_t LSB = CE->getValue();
3632 // The LSB must be in the range [0,31]
3633 if (LSB < 0 || LSB > 31) {
3634 Error(E, "'lsb' operand must be in the range [0,31]");
3635 return MatchOperand_ParseFail;
3636 }
3637 E = Parser.getTok().getLoc();
3638
3639 // Expect another immediate operand.
3640 if (Parser.getTok().isNot(AsmToken::Comma)) {
3641 Error(Parser.getTok().getLoc(), "too few operands");
3642 return MatchOperand_ParseFail;
3643 }
3644 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003645 if (Parser.getTok().isNot(AsmToken::Hash) &&
3646 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003647 Error(Parser.getTok().getLoc(), "'#' expected");
3648 return MatchOperand_ParseFail;
3649 }
3650 Parser.Lex(); // Eat hash token.
3651
3652 const MCExpr *WidthExpr;
3653 if (getParser().ParseExpression(WidthExpr)) {
3654 Error(E, "malformed immediate expression");
3655 return MatchOperand_ParseFail;
3656 }
3657 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3658 if (!CE) {
3659 Error(E, "'width' operand must be an immediate");
3660 return MatchOperand_ParseFail;
3661 }
3662
3663 int64_t Width = CE->getValue();
3664 // The LSB must be in the range [1,32-lsb]
3665 if (Width < 1 || Width > 32 - LSB) {
3666 Error(E, "'width' operand must be in the range [1,32-lsb]");
3667 return MatchOperand_ParseFail;
3668 }
3669 E = Parser.getTok().getLoc();
3670
3671 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3672
3673 return MatchOperand_Success;
3674}
3675
Jim Grosbachd3595712011-08-03 23:50:40 +00003676ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3677parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3678 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003679 // postidx_reg := '+' register {, shift}
3680 // | '-' register {, shift}
3681 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003682
3683 // This method must return MatchOperand_NoMatch without consuming any tokens
3684 // in the case where there is no match, as other alternatives take other
3685 // parse methods.
3686 AsmToken Tok = Parser.getTok();
3687 SMLoc S = Tok.getLoc();
3688 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003689 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003690 int Reg = -1;
3691 if (Tok.is(AsmToken::Plus)) {
3692 Parser.Lex(); // Eat the '+' token.
3693 haveEaten = true;
3694 } else if (Tok.is(AsmToken::Minus)) {
3695 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003696 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003697 haveEaten = true;
3698 }
3699 if (Parser.getTok().is(AsmToken::Identifier))
3700 Reg = tryParseRegister();
3701 if (Reg == -1) {
3702 if (!haveEaten)
3703 return MatchOperand_NoMatch;
3704 Error(Parser.getTok().getLoc(), "register expected");
3705 return MatchOperand_ParseFail;
3706 }
3707 SMLoc E = Parser.getTok().getLoc();
3708
Jim Grosbachc320c852011-08-05 21:28:30 +00003709 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3710 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003711 if (Parser.getTok().is(AsmToken::Comma)) {
3712 Parser.Lex(); // Eat the ','.
3713 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3714 return MatchOperand_ParseFail;
3715 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003716
3717 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3718 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003719
3720 return MatchOperand_Success;
3721}
3722
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003723ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3724parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3725 // Check for a post-index addressing register operand. Specifically:
3726 // am3offset := '+' register
3727 // | '-' register
3728 // | register
3729 // | # imm
3730 // | # + imm
3731 // | # - imm
3732
3733 // This method must return MatchOperand_NoMatch without consuming any tokens
3734 // in the case where there is no match, as other alternatives take other
3735 // parse methods.
3736 AsmToken Tok = Parser.getTok();
3737 SMLoc S = Tok.getLoc();
3738
3739 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003740 if (Parser.getTok().is(AsmToken::Hash) ||
3741 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003742 Parser.Lex(); // Eat the '#'.
3743 // Explicitly look for a '-', as we need to encode negative zero
3744 // differently.
3745 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3746 const MCExpr *Offset;
3747 if (getParser().ParseExpression(Offset))
3748 return MatchOperand_ParseFail;
3749 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3750 if (!CE) {
3751 Error(S, "constant expression expected");
3752 return MatchOperand_ParseFail;
3753 }
3754 SMLoc E = Tok.getLoc();
3755 // Negative zero is encoded as the flag value INT32_MIN.
3756 int32_t Val = CE->getValue();
3757 if (isNegative && Val == 0)
3758 Val = INT32_MIN;
3759
3760 Operands.push_back(
3761 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3762
3763 return MatchOperand_Success;
3764 }
3765
3766
3767 bool haveEaten = false;
3768 bool isAdd = true;
3769 int Reg = -1;
3770 if (Tok.is(AsmToken::Plus)) {
3771 Parser.Lex(); // Eat the '+' token.
3772 haveEaten = true;
3773 } else if (Tok.is(AsmToken::Minus)) {
3774 Parser.Lex(); // Eat the '-' token.
3775 isAdd = false;
3776 haveEaten = true;
3777 }
3778 if (Parser.getTok().is(AsmToken::Identifier))
3779 Reg = tryParseRegister();
3780 if (Reg == -1) {
3781 if (!haveEaten)
3782 return MatchOperand_NoMatch;
3783 Error(Parser.getTok().getLoc(), "register expected");
3784 return MatchOperand_ParseFail;
3785 }
3786 SMLoc E = Parser.getTok().getLoc();
3787
3788 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3789 0, S, E));
3790
3791 return MatchOperand_Success;
3792}
3793
Jim Grosbach7db8d692011-09-08 22:07:06 +00003794/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3795/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3796/// when they refer multiple MIOperands inside a single one.
3797bool ARMAsmParser::
3798cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3799 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3800 // Rt, Rt2
3801 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3802 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3803 // Create a writeback register dummy placeholder.
3804 Inst.addOperand(MCOperand::CreateReg(0));
3805 // addr
3806 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3807 // pred
3808 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3809 return true;
3810}
3811
3812/// cvtT2StrdPre - Convert parsed operands to MCInst.
3813/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3814/// when they refer multiple MIOperands inside a single one.
3815bool ARMAsmParser::
3816cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3817 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3818 // Create a writeback register dummy placeholder.
3819 Inst.addOperand(MCOperand::CreateReg(0));
3820 // Rt, Rt2
3821 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3822 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3823 // addr
3824 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3825 // pred
3826 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3827 return true;
3828}
3829
Jim Grosbachc086f682011-09-08 00:39:19 +00003830/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3831/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3832/// when they refer multiple MIOperands inside a single one.
3833bool ARMAsmParser::
3834cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3835 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3836 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3837
3838 // Create a writeback register dummy placeholder.
3839 Inst.addOperand(MCOperand::CreateImm(0));
3840
3841 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3842 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3843 return true;
3844}
3845
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003846/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3847/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3848/// when they refer multiple MIOperands inside a single one.
3849bool ARMAsmParser::
3850cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3851 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3852 // Create a writeback register dummy placeholder.
3853 Inst.addOperand(MCOperand::CreateImm(0));
3854 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3855 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3856 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3857 return true;
3858}
3859
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003860/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003861/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3862/// when they refer multiple MIOperands inside a single one.
3863bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003864cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003865 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3866 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3867
3868 // Create a writeback register dummy placeholder.
3869 Inst.addOperand(MCOperand::CreateImm(0));
3870
Jim Grosbachd3595712011-08-03 23:50:40 +00003871 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003872 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3873 return true;
3874}
3875
Owen Anderson16d33f32011-08-26 20:43:14 +00003876/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3877/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3878/// when they refer multiple MIOperands inside a single one.
3879bool ARMAsmParser::
3880cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3881 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3882 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3883
3884 // Create a writeback register dummy placeholder.
3885 Inst.addOperand(MCOperand::CreateImm(0));
3886
3887 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3888 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3889 return true;
3890}
3891
3892
Jim Grosbachd564bf32011-08-11 19:22:40 +00003893/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3894/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3895/// when they refer multiple MIOperands inside a single one.
3896bool ARMAsmParser::
3897cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3898 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3899 // Create a writeback register dummy placeholder.
3900 Inst.addOperand(MCOperand::CreateImm(0));
3901 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3902 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3903 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3904 return true;
3905}
3906
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003907/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003908/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3909/// when they refer multiple MIOperands inside a single one.
3910bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003911cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003912 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3913 // Create a writeback register dummy placeholder.
3914 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003915 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3916 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3917 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003918 return true;
3919}
3920
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003921/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3922/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3923/// when they refer multiple MIOperands inside a single one.
3924bool ARMAsmParser::
3925cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3926 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3927 // Create a writeback register dummy placeholder.
3928 Inst.addOperand(MCOperand::CreateImm(0));
3929 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3930 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3931 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3932 return true;
3933}
3934
Jim Grosbachd3595712011-08-03 23:50:40 +00003935/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3936/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3937/// when they refer multiple MIOperands inside a single one.
3938bool ARMAsmParser::
3939cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3940 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3941 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003942 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003943 // Create a writeback register dummy placeholder.
3944 Inst.addOperand(MCOperand::CreateImm(0));
3945 // addr
3946 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3947 // offset
3948 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3949 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003950 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3951 return true;
3952}
3953
Jim Grosbachd3595712011-08-03 23:50:40 +00003954/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003955/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3956/// when they refer multiple MIOperands inside a single one.
3957bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003958cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3959 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3960 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003961 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003962 // Create a writeback register dummy placeholder.
3963 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003964 // addr
3965 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3966 // offset
3967 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3968 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003969 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3970 return true;
3971}
3972
Jim Grosbachd3595712011-08-03 23:50:40 +00003973/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003974/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3975/// when they refer multiple MIOperands inside a single one.
3976bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003977cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3978 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003979 // Create a writeback register dummy placeholder.
3980 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003981 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003982 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003983 // addr
3984 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3985 // offset
3986 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3987 // pred
3988 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3989 return true;
3990}
3991
3992/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3993/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3994/// when they refer multiple MIOperands inside a single one.
3995bool ARMAsmParser::
3996cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3997 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3998 // Create a writeback register dummy placeholder.
3999 Inst.addOperand(MCOperand::CreateImm(0));
4000 // Rt
4001 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4002 // addr
4003 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4004 // offset
4005 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
4006 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00004007 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4008 return true;
4009}
4010
Jim Grosbach5b96b802011-08-10 20:29:19 +00004011/// cvtLdrdPre - Convert parsed operands to MCInst.
4012/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4013/// when they refer multiple MIOperands inside a single one.
4014bool ARMAsmParser::
4015cvtLdrdPre(MCInst &Inst, unsigned Opcode,
4016 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4017 // Rt, Rt2
4018 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4019 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4020 // Create a writeback register dummy placeholder.
4021 Inst.addOperand(MCOperand::CreateImm(0));
4022 // addr
4023 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4024 // pred
4025 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4026 return true;
4027}
4028
Jim Grosbacheb09f492011-08-11 20:28:23 +00004029/// cvtStrdPre - Convert parsed operands to MCInst.
4030/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4031/// when they refer multiple MIOperands inside a single one.
4032bool ARMAsmParser::
4033cvtStrdPre(MCInst &Inst, unsigned Opcode,
4034 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4035 // Create a writeback register dummy placeholder.
4036 Inst.addOperand(MCOperand::CreateImm(0));
4037 // Rt, Rt2
4038 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4039 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4040 // addr
4041 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4042 // pred
4043 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4044 return true;
4045}
4046
Jim Grosbachcd4dd252011-08-10 22:42:16 +00004047/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
4048/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4049/// when they refer multiple MIOperands inside a single one.
4050bool ARMAsmParser::
4051cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
4052 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4053 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4054 // Create a writeback register dummy placeholder.
4055 Inst.addOperand(MCOperand::CreateImm(0));
4056 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4057 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4058 return true;
4059}
4060
Jim Grosbach8e048492011-08-19 22:07:46 +00004061/// cvtThumbMultiple- Convert parsed operands to MCInst.
4062/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4063/// when they refer multiple MIOperands inside a single one.
4064bool ARMAsmParser::
4065cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4066 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4067 // The second source operand must be the same register as the destination
4068 // operand.
4069 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00004070 (((ARMOperand*)Operands[3])->getReg() !=
4071 ((ARMOperand*)Operands[5])->getReg()) &&
4072 (((ARMOperand*)Operands[3])->getReg() !=
4073 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00004074 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00004075 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00004076 return false;
4077 }
4078 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4079 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00004080 // If we have a three-operand form, make sure to set Rn to be the operand
4081 // that isn't the same as Rd.
4082 unsigned RegOp = 4;
4083 if (Operands.size() == 6 &&
4084 ((ARMOperand*)Operands[4])->getReg() ==
4085 ((ARMOperand*)Operands[3])->getReg())
4086 RegOp = 5;
4087 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4088 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00004089 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4090
4091 return true;
4092}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00004093
Jim Grosbach3ea06572011-10-24 22:16:58 +00004094bool ARMAsmParser::
4095cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4096 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4097 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00004098 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00004099 // Create a writeback register dummy placeholder.
4100 Inst.addOperand(MCOperand::CreateImm(0));
4101 // Vn
4102 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4103 // pred
4104 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4105 return true;
4106}
4107
4108bool ARMAsmParser::
4109cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4110 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4111 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00004112 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00004113 // Create a writeback register dummy placeholder.
4114 Inst.addOperand(MCOperand::CreateImm(0));
4115 // Vn
4116 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4117 // Vm
4118 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4119 // pred
4120 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4121 return true;
4122}
4123
Jim Grosbach05df4602011-10-31 21:50:31 +00004124bool ARMAsmParser::
4125cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4126 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4127 // Create a writeback register dummy placeholder.
4128 Inst.addOperand(MCOperand::CreateImm(0));
4129 // Vn
4130 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4131 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00004132 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00004133 // pred
4134 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4135 return true;
4136}
4137
4138bool ARMAsmParser::
4139cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4140 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4141 // Create a writeback register dummy placeholder.
4142 Inst.addOperand(MCOperand::CreateImm(0));
4143 // Vn
4144 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4145 // Vm
4146 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4147 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00004148 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00004149 // pred
4150 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4151 return true;
4152}
4153
Bill Wendlinge18980a2010-11-06 22:36:58 +00004154/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004155/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00004156bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00004157parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004158 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00004159 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00004160 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004161 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004162 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004163
Sean Callanan936b0d32010-01-19 21:44:56 +00004164 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004165 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00004166 if (BaseRegNum == -1)
4167 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004168
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004169 // The next token must either be a comma or a closing bracket.
4170 const AsmToken &Tok = Parser.getTok();
4171 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00004172 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004173
Jim Grosbachd3595712011-08-03 23:50:40 +00004174 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004175 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004176 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004177
Jim Grosbachd3595712011-08-03 23:50:40 +00004178 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004179 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00004180
Jim Grosbach40700e02011-09-19 18:42:21 +00004181 // If there's a pre-indexing writeback marker, '!', just add it as a token
4182 // operand. It's rather odd, but syntactically valid.
4183 if (Parser.getTok().is(AsmToken::Exclaim)) {
4184 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4185 Parser.Lex(); // Eat the '!'.
4186 }
4187
Jim Grosbachd3595712011-08-03 23:50:40 +00004188 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004189 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004190
Jim Grosbachd3595712011-08-03 23:50:40 +00004191 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4192 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004193
Jim Grosbacha95ec992011-10-11 17:29:55 +00004194 // If we have a ':', it's an alignment specifier.
4195 if (Parser.getTok().is(AsmToken::Colon)) {
4196 Parser.Lex(); // Eat the ':'.
4197 E = Parser.getTok().getLoc();
4198
4199 const MCExpr *Expr;
4200 if (getParser().ParseExpression(Expr))
4201 return true;
4202
4203 // The expression has to be a constant. Memory references with relocations
4204 // don't come through here, as they use the <label> forms of the relevant
4205 // instructions.
4206 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4207 if (!CE)
4208 return Error (E, "constant expression expected");
4209
4210 unsigned Align = 0;
4211 switch (CE->getValue()) {
4212 default:
Jim Grosbachcef98cd2011-12-19 18:31:43 +00004213 return Error(E,
4214 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4215 case 16: Align = 2; break;
4216 case 32: Align = 4; break;
Jim Grosbacha95ec992011-10-11 17:29:55 +00004217 case 64: Align = 8; break;
4218 case 128: Align = 16; break;
4219 case 256: Align = 32; break;
4220 }
4221
4222 // Now we should have the closing ']'
4223 E = Parser.getTok().getLoc();
4224 if (Parser.getTok().isNot(AsmToken::RBrac))
4225 return Error(E, "']' expected");
4226 Parser.Lex(); // Eat right bracket token.
4227
4228 // Don't worry about range checking the value here. That's handled by
4229 // the is*() predicates.
4230 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4231 ARM_AM::no_shift, 0, Align,
4232 false, S, E));
4233
4234 // If there's a pre-indexing writeback marker, '!', just add it as a token
4235 // operand.
4236 if (Parser.getTok().is(AsmToken::Exclaim)) {
4237 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4238 Parser.Lex(); // Eat the '!'.
4239 }
4240
4241 return false;
4242 }
4243
4244 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00004245 // offset. Be friendly and also accept a plain integer (without a leading
4246 // hash) for gas compatibility.
4247 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004248 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00004249 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004250 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00004251 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00004252 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004253
Owen Anderson967674d2011-08-29 19:36:44 +00004254 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00004255 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004256 if (getParser().ParseExpression(Offset))
4257 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004258
4259 // The expression has to be a constant. Memory references with relocations
4260 // don't come through here, as they use the <label> forms of the relevant
4261 // instructions.
4262 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4263 if (!CE)
4264 return Error (E, "constant expression expected");
4265
Owen Anderson967674d2011-08-29 19:36:44 +00004266 // If the constant was #-0, represent it as INT32_MIN.
4267 int32_t Val = CE->getValue();
4268 if (isNegative && Val == 0)
4269 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4270
Jim Grosbachd3595712011-08-03 23:50:40 +00004271 // Now we should have the closing ']'
4272 E = Parser.getTok().getLoc();
4273 if (Parser.getTok().isNot(AsmToken::RBrac))
4274 return Error(E, "']' expected");
4275 Parser.Lex(); // Eat right bracket token.
4276
4277 // Don't worry about range checking the value here. That's handled by
4278 // the is*() predicates.
4279 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004280 ARM_AM::no_shift, 0, 0,
4281 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004282
4283 // If there's a pre-indexing writeback marker, '!', just add it as a token
4284 // operand.
4285 if (Parser.getTok().is(AsmToken::Exclaim)) {
4286 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4287 Parser.Lex(); // Eat the '!'.
4288 }
4289
4290 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004291 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004292
4293 // The register offset is optionally preceded by a '+' or '-'
4294 bool isNegative = false;
4295 if (Parser.getTok().is(AsmToken::Minus)) {
4296 isNegative = true;
4297 Parser.Lex(); // Eat the '-'.
4298 } else if (Parser.getTok().is(AsmToken::Plus)) {
4299 // Nothing to do.
4300 Parser.Lex(); // Eat the '+'.
4301 }
4302
4303 E = Parser.getTok().getLoc();
4304 int OffsetRegNum = tryParseRegister();
4305 if (OffsetRegNum == -1)
4306 return Error(E, "register expected");
4307
4308 // If there's a shift operator, handle it.
4309 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004310 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004311 if (Parser.getTok().is(AsmToken::Comma)) {
4312 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004313 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004314 return true;
4315 }
4316
4317 // Now we should have the closing ']'
4318 E = Parser.getTok().getLoc();
4319 if (Parser.getTok().isNot(AsmToken::RBrac))
4320 return Error(E, "']' expected");
4321 Parser.Lex(); // Eat right bracket token.
4322
4323 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004324 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004325 S, E));
4326
Jim Grosbachc320c852011-08-05 21:28:30 +00004327 // If there's a pre-indexing writeback marker, '!', just add it as a token
4328 // operand.
4329 if (Parser.getTok().is(AsmToken::Exclaim)) {
4330 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4331 Parser.Lex(); // Eat the '!'.
4332 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004333
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004334 return false;
4335}
4336
Jim Grosbachd3595712011-08-03 23:50:40 +00004337/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004338/// ( lsl | lsr | asr | ror ) , # shift_amount
4339/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004340/// return true if it parses a shift otherwise it returns false.
4341bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4342 unsigned &Amount) {
4343 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004344 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004345 if (Tok.isNot(AsmToken::Identifier))
4346 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004347 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004348 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4349 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004350 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004351 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004352 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004353 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004354 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004355 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004356 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004357 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004358 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004359 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004360 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004361 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004362
Jim Grosbachd3595712011-08-03 23:50:40 +00004363 // rrx stands alone.
4364 Amount = 0;
4365 if (St != ARM_AM::rrx) {
4366 Loc = Parser.getTok().getLoc();
4367 // A '#' and a shift amount.
4368 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004369 if (HashTok.isNot(AsmToken::Hash) &&
4370 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004371 return Error(HashTok.getLoc(), "'#' expected");
4372 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004373
Jim Grosbachd3595712011-08-03 23:50:40 +00004374 const MCExpr *Expr;
4375 if (getParser().ParseExpression(Expr))
4376 return true;
4377 // Range check the immediate.
4378 // lsl, ror: 0 <= imm <= 31
4379 // lsr, asr: 0 <= imm <= 32
4380 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4381 if (!CE)
4382 return Error(Loc, "shift amount must be an immediate");
4383 int64_t Imm = CE->getValue();
4384 if (Imm < 0 ||
4385 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4386 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4387 return Error(Loc, "immediate shift value out of range");
4388 Amount = Imm;
4389 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004390
4391 return false;
4392}
4393
Jim Grosbache7fbce72011-10-03 23:38:36 +00004394/// parseFPImm - A floating point immediate expression operand.
4395ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4396parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004397 // Anything that can accept a floating point constant as an operand
4398 // needs to go through here, as the regular ParseExpression is
4399 // integer only.
4400 //
4401 // This routine still creates a generic Immediate operand, containing
4402 // a bitcast of the 64-bit floating point value. The various operands
4403 // that accept floats can check whether the value is valid for them
4404 // via the standard is*() predicates.
4405
Jim Grosbache7fbce72011-10-03 23:38:36 +00004406 SMLoc S = Parser.getTok().getLoc();
4407
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004408 if (Parser.getTok().isNot(AsmToken::Hash) &&
4409 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004410 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004411
4412 // Disambiguate the VMOV forms that can accept an FP immediate.
4413 // vmov.f32 <sreg>, #imm
4414 // vmov.f64 <dreg>, #imm
4415 // vmov.f32 <dreg>, #imm @ vector f32x2
4416 // vmov.f32 <qreg>, #imm @ vector f32x4
4417 //
4418 // There are also the NEON VMOV instructions which expect an
4419 // integer constant. Make sure we don't try to parse an FPImm
4420 // for these:
4421 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4422 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4423 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4424 TyOp->getToken() != ".f64"))
4425 return MatchOperand_NoMatch;
4426
Jim Grosbache7fbce72011-10-03 23:38:36 +00004427 Parser.Lex(); // Eat the '#'.
4428
4429 // Handle negation, as that still comes through as a separate token.
4430 bool isNegative = false;
4431 if (Parser.getTok().is(AsmToken::Minus)) {
4432 isNegative = true;
4433 Parser.Lex();
4434 }
4435 const AsmToken &Tok = Parser.getTok();
Jim Grosbach235c8d22012-01-19 02:47:30 +00004436 SMLoc Loc = Tok.getLoc();
Jim Grosbache7fbce72011-10-03 23:38:36 +00004437 if (Tok.is(AsmToken::Real)) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004438 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbache7fbce72011-10-03 23:38:36 +00004439 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4440 // If we had a '-' in front, toggle the sign bit.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004441 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbache7fbce72011-10-03 23:38:36 +00004442 Parser.Lex(); // Eat the token.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004443 Operands.push_back(ARMOperand::CreateImm(
4444 MCConstantExpr::Create(IntVal, getContext()),
4445 S, Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004446 return MatchOperand_Success;
4447 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004448 // Also handle plain integers. Instructions which allow floating point
4449 // immediates also allow a raw encoded 8-bit value.
Jim Grosbache7fbce72011-10-03 23:38:36 +00004450 if (Tok.is(AsmToken::Integer)) {
4451 int64_t Val = Tok.getIntVal();
4452 Parser.Lex(); // Eat the token.
4453 if (Val > 255 || Val < 0) {
Jim Grosbach235c8d22012-01-19 02:47:30 +00004454 Error(Loc, "encoded floating point value out of range");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004455 return MatchOperand_ParseFail;
4456 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004457 double RealVal = ARM_AM::getFPImmFloat(Val);
4458 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4459 Operands.push_back(ARMOperand::CreateImm(
4460 MCConstantExpr::Create(Val, getContext()), S,
4461 Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004462 return MatchOperand_Success;
4463 }
4464
Jim Grosbach235c8d22012-01-19 02:47:30 +00004465 Error(Loc, "invalid floating point immediate");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004466 return MatchOperand_ParseFail;
4467}
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004468
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004469/// Parse a arm instruction operand. For now this parses the operand regardless
4470/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004471bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004472 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004473 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004474
4475 // Check if the current operand has a custom associated parser, if so, try to
4476 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004477 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4478 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004479 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004480 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4481 // there was a match, but an error occurred, in which case, just return that
4482 // the operand parsing failed.
4483 if (ResTy == MatchOperand_ParseFail)
4484 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004485
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004486 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004487 default:
4488 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004489 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004490 case AsmToken::Identifier: {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004491 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004492 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004493 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004494 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004495 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004496 else if (Res == -1) // irrecoverable error
4497 return true;
Jim Grosbach4eda1452011-12-20 22:26:38 +00004498 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachd28888d2012-03-15 21:34:14 +00004499 if (Mnemonic == "vmrs" &&
4500 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004501 S = Parser.getTok().getLoc();
4502 Parser.Lex();
Jim Grosbachd28888d2012-03-15 21:34:14 +00004503 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004504 return false;
4505 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004506
4507 // Fall though for the Identifier case that is not a register or a
4508 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004509 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004510 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004511 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004512 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004513 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004514 // This was not a register so parse other operands that start with an
4515 // identifier (like labels) as expressions and create them as immediates.
4516 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004517 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004518 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004519 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004520 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004521 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4522 return false;
4523 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004524 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004525 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004526 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004527 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004528 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004529 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004530 // #42 -> immediate.
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004531 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004532 Parser.Lex();
Jim Grosbach003607f2012-04-16 21:18:46 +00004533
4534 if (Parser.getTok().isNot(AsmToken::Colon)) {
4535 bool isNegative = Parser.getTok().is(AsmToken::Minus);
4536 const MCExpr *ImmVal;
4537 if (getParser().ParseExpression(ImmVal))
4538 return true;
4539 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
4540 if (CE) {
4541 int32_t Val = CE->getValue();
4542 if (isNegative && Val == 0)
4543 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
4544 }
4545 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4546 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4547 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004548 }
Jim Grosbach003607f2012-04-16 21:18:46 +00004549 // w/ a ':' after the '#', it's just like a plain ':'.
4550 // FALLTHROUGH
Owen Andersonf02d98d2011-08-29 17:17:09 +00004551 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004552 case AsmToken::Colon: {
4553 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004554 // FIXME: Check it's an expression prefix,
4555 // e.g. (FOO - :lower16:BAR) isn't legal.
4556 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004557 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004558 return true;
4559
Evan Cheng965b3c72011-01-13 07:58:56 +00004560 const MCExpr *SubExprVal;
4561 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004562 return true;
4563
Evan Cheng965b3c72011-01-13 07:58:56 +00004564 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4565 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004566 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004567 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004568 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004569 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004570 }
4571}
4572
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004573// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004574// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004575bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004576 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004577
4578 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004579 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004580 Parser.Lex(); // Eat ':'
4581
4582 if (getLexer().isNot(AsmToken::Identifier)) {
4583 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4584 return true;
4585 }
4586
4587 StringRef IDVal = Parser.getTok().getIdentifier();
4588 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004589 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004590 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004591 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004592 } else {
4593 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4594 return true;
4595 }
4596 Parser.Lex();
4597
4598 if (getLexer().isNot(AsmToken::Colon)) {
4599 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4600 return true;
4601 }
4602 Parser.Lex(); // Eat the last ':'
4603 return false;
4604}
4605
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004606/// \brief Given a mnemonic, split out possible predication code and carry
4607/// setting letters to form a canonical mnemonic and flags.
4608//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004609// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004610// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004611StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004612 unsigned &PredicationCode,
4613 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004614 unsigned &ProcessorIMod,
4615 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004616 PredicationCode = ARMCC::AL;
4617 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004618 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004619
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004620 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004621 //
4622 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004623 if ((Mnemonic == "movs" && isThumb()) ||
4624 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4625 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4626 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4627 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4628 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4629 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004630 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4631 Mnemonic == "fmuls")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004632 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004633
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004634 // First, split out any predication code. Ignore mnemonics we know aren't
4635 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004636 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004637 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004638 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004639 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004640 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4641 .Case("eq", ARMCC::EQ)
4642 .Case("ne", ARMCC::NE)
4643 .Case("hs", ARMCC::HS)
4644 .Case("cs", ARMCC::HS)
4645 .Case("lo", ARMCC::LO)
4646 .Case("cc", ARMCC::LO)
4647 .Case("mi", ARMCC::MI)
4648 .Case("pl", ARMCC::PL)
4649 .Case("vs", ARMCC::VS)
4650 .Case("vc", ARMCC::VC)
4651 .Case("hi", ARMCC::HI)
4652 .Case("ls", ARMCC::LS)
4653 .Case("ge", ARMCC::GE)
4654 .Case("lt", ARMCC::LT)
4655 .Case("gt", ARMCC::GT)
4656 .Case("le", ARMCC::LE)
4657 .Case("al", ARMCC::AL)
4658 .Default(~0U);
4659 if (CC != ~0U) {
4660 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4661 PredicationCode = CC;
4662 }
Bill Wendling193961b2010-10-29 23:50:21 +00004663 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004664
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004665 // Next, determine if we have a carry setting bit. We explicitly ignore all
4666 // the instructions we know end in 's'.
4667 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004668 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004669 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4670 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4671 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004672 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004673 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach92a939a2011-12-19 19:02:41 +00004674 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbachd74560b2012-03-15 20:48:18 +00004675 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Evan Chengaca6c822012-04-11 00:13:00 +00004676 Mnemonic == "vfms" || Mnemonic == "vfnms" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004677 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004678 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4679 CarrySetting = true;
4680 }
4681
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004682 // The "cps" instruction can have a interrupt mode operand which is glued into
4683 // the mnemonic. Check if this is the case, split it and parse the imod op
4684 if (Mnemonic.startswith("cps")) {
4685 // Split out any imod code.
4686 unsigned IMod =
4687 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4688 .Case("ie", ARM_PROC::IE)
4689 .Case("id", ARM_PROC::ID)
4690 .Default(~0U);
4691 if (IMod != ~0U) {
4692 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4693 ProcessorIMod = IMod;
4694 }
4695 }
4696
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004697 // The "it" instruction has the condition mask on the end of the mnemonic.
4698 if (Mnemonic.startswith("it")) {
4699 ITMask = Mnemonic.slice(2, Mnemonic.size());
4700 Mnemonic = Mnemonic.slice(0, 2);
4701 }
4702
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004703 return Mnemonic;
4704}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004705
4706/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4707/// inclusion of carry set or predication code operands.
4708//
4709// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004710void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004711getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004712 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004713 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4714 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004715 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004716 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004717 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004718 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004719 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Evan Chengaca6c822012-04-11 00:13:00 +00004720 Mnemonic == "vfm" || Mnemonic == "vfnm" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004721 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004722 Mnemonic == "mla" || Mnemonic == "smlal" ||
4723 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004724 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004725 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004726 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004727
Daniel Dunbar09264122011-01-11 19:06:29 +00004728 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4729 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4730 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4731 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004732 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4733 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004734 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004735 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4736 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4737 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004738 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4739 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004740 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004741 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004742 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004743 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004744
Jim Grosbach6c45b752011-09-16 16:39:25 +00004745 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004746 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004747 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004748 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004749 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004750}
4751
Jim Grosbach7283da92011-08-16 21:12:37 +00004752bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4753 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004754 // FIXME: This is all horribly hacky. We really need a better way to deal
4755 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004756
4757 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4758 // another does not. Specifically, the MOVW instruction does not. So we
4759 // special case it here and remove the defaulted (non-setting) cc_out
4760 // operand if that's the instruction we're trying to match.
4761 //
4762 // We do this as post-processing of the explicit operands rather than just
4763 // conditionally adding the cc_out in the first place because we need
4764 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004765 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004766 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4767 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4768 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4769 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004770
4771 // Register-register 'add' for thumb does not have a cc_out operand
4772 // when there are only two register operands.
4773 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4774 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4775 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4776 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4777 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004778 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004779 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4780 // have to check the immediate range here since Thumb2 has a variant
4781 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004782 if (((isThumb() && Mnemonic == "add") ||
4783 (isThumbTwo() && Mnemonic == "sub")) &&
4784 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004785 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4786 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4787 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004788 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
Jim Grosbachdf5a2442012-04-10 17:31:55 +00004789 ((Mnemonic == "add" &&static_cast<ARMOperand*>(Operands[5])->isReg()) ||
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004790 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004791 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004792 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4793 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004794 // selecting via the generic "add" mnemonic, so to know that we
4795 // should remove the cc_out operand, we have to explicitly check that
4796 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004797 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4798 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004799 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4800 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4801 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4802 // Nest conditions rather than one big 'if' statement for readability.
4803 //
4804 // If either register is a high reg, it's either one of the SP
4805 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004806 // check against T3. If the second register is the PC, this is an
4807 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004808 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4809 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004810 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004811 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4812 return false;
4813 // If both registers are low, we're in an IT block, and the immediate is
4814 // in range, we should use encoding T1 instead, which has a cc_out.
4815 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004816 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004817 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4818 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4819 return false;
4820
4821 // Otherwise, we use encoding T4, which does not have a cc_out
4822 // operand.
4823 return true;
4824 }
4825
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004826 // The thumb2 multiply instruction doesn't have a CCOut register, so
4827 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4828 // use the 16-bit encoding or not.
4829 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4830 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4831 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4832 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4833 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4834 // If the registers aren't low regs, the destination reg isn't the
4835 // same as one of the source regs, or the cc_out operand is zero
4836 // outside of an IT block, we have to use the 32-bit encoding, so
4837 // remove the cc_out operand.
4838 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4839 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004840 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004841 !inITBlock() ||
4842 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4843 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4844 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4845 static_cast<ARMOperand*>(Operands[4])->getReg())))
4846 return true;
4847
Jim Grosbachefa7e952011-11-15 19:55:16 +00004848 // Also check the 'mul' syntax variant that doesn't specify an explicit
4849 // destination register.
4850 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4851 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4852 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4853 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4854 // If the registers aren't low regs or the cc_out operand is zero
4855 // outside of an IT block, we have to use the 32-bit encoding, so
4856 // remove the cc_out operand.
4857 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4858 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4859 !inITBlock()))
4860 return true;
4861
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004862
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004863
Jim Grosbach4b701af2011-08-24 21:42:27 +00004864 // Register-register 'add/sub' for thumb does not have a cc_out operand
4865 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4866 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4867 // right, this will result in better diagnostics (which operand is off)
4868 // anyway.
4869 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4870 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004871 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4872 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
Jim Grosbachdf5a2442012-04-10 17:31:55 +00004873 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4874 (static_cast<ARMOperand*>(Operands[4])->isImm() ||
4875 (Operands.size() == 6 &&
4876 static_cast<ARMOperand*>(Operands[5])->isImm())))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004877 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004878
Jim Grosbach7283da92011-08-16 21:12:37 +00004879 return false;
4880}
4881
Jim Grosbach12952fe2011-11-11 23:08:10 +00004882static bool isDataTypeToken(StringRef Tok) {
4883 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4884 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4885 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4886 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4887 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4888 Tok == ".f" || Tok == ".d";
4889}
4890
4891// FIXME: This bit should probably be handled via an explicit match class
4892// in the .td files that matches the suffix instead of having it be
4893// a literal string token the way it is now.
4894static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4895 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4896}
4897
Jim Grosbach8be2f652011-12-09 23:34:09 +00004898static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004899/// Parse an arm instruction mnemonic followed by its operands.
4900bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4901 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004902 // Apply mnemonic aliases before doing anything else, as the destination
4903 // mnemnonic may include suffices and we want to handle them normally.
4904 // The generic tblgen'erated code does this later, at the start of
4905 // MatchInstructionImpl(), but that's too late for aliases that include
4906 // any sort of suffix.
4907 unsigned AvailableFeatures = getAvailableFeatures();
4908 applyMnemonicAliases(Name, AvailableFeatures);
4909
Jim Grosbachab5830e2011-12-14 02:16:11 +00004910 // First check for the ARM-specific .req directive.
4911 if (Parser.getTok().is(AsmToken::Identifier) &&
4912 Parser.getTok().getIdentifier() == ".req") {
4913 parseDirectiveReq(Name, NameLoc);
4914 // We always return 'error' for this, as we're done with this
4915 // statement and don't need to match the 'instruction."
4916 return true;
4917 }
4918
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004919 // Create the leading tokens for the mnemonic, split by '.' characters.
4920 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004921 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004922
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004923 // Split out the predication code and carry setting flag from the mnemonic.
4924 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004925 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004926 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004927 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004928 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004929 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004930
Jim Grosbach1c171b12011-08-25 17:23:55 +00004931 // In Thumb1, only the branch (B) instruction can be predicated.
4932 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4933 Parser.EatToEndOfStatement();
4934 return Error(NameLoc, "conditional execution not supported in Thumb1");
4935 }
4936
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004937 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4938
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004939 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4940 // is the mask as it will be for the IT encoding if the conditional
4941 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4942 // where the conditional bit0 is zero, the instruction post-processing
4943 // will adjust the mask accordingly.
4944 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004945 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4946 if (ITMask.size() > 3) {
4947 Parser.EatToEndOfStatement();
4948 return Error(Loc, "too many conditions on IT instruction");
4949 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004950 unsigned Mask = 8;
4951 for (unsigned i = ITMask.size(); i != 0; --i) {
4952 char pos = ITMask[i - 1];
4953 if (pos != 't' && pos != 'e') {
4954 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004955 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004956 }
4957 Mask >>= 1;
4958 if (ITMask[i - 1] == 't')
4959 Mask |= 8;
4960 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004961 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004962 }
4963
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004964 // FIXME: This is all a pretty gross hack. We should automatically handle
4965 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004966
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004967 // Next, add the CCOut and ConditionCode operands, if needed.
4968 //
4969 // For mnemonics which can ever incorporate a carry setting bit or predication
4970 // code, our matching model involves us always generating CCOut and
4971 // ConditionCode operands to match the mnemonic "as written" and then we let
4972 // the matcher deal with finding the right instruction or generating an
4973 // appropriate error.
4974 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004975 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004976
Jim Grosbach03a8a162011-07-14 22:04:21 +00004977 // If we had a carry-set on an instruction that can't do that, issue an
4978 // error.
4979 if (!CanAcceptCarrySet && CarrySetting) {
4980 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004981 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004982 "' can not set flags, but 's' suffix specified");
4983 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004984 // If we had a predication code on an instruction that can't do that, issue an
4985 // error.
4986 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4987 Parser.EatToEndOfStatement();
4988 return Error(NameLoc, "instruction '" + Mnemonic +
4989 "' is not predicable, but condition code specified");
4990 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004991
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004992 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004993 if (CanAcceptCarrySet) {
4994 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004995 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004996 Loc));
4997 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004998
4999 // Add the predication code operand, if necessary.
5000 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005001 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
5002 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005003 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00005004 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00005005 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00005006
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00005007 // Add the processor imod operand, if necessary.
5008 if (ProcessorIMod) {
5009 Operands.push_back(ARMOperand::CreateImm(
5010 MCConstantExpr::Create(ProcessorIMod, getContext()),
5011 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00005012 }
5013
Daniel Dunbar188b47b2010-08-11 06:37:20 +00005014 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00005015 while (Next != StringRef::npos) {
5016 Start = Next;
5017 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00005018 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005019
Jim Grosbach12952fe2011-11-11 23:08:10 +00005020 // Some NEON instructions have an optional datatype suffix that is
5021 // completely ignored. Check for that.
5022 if (isDataTypeToken(ExtraToken) &&
5023 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
5024 continue;
5025
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00005026 if (ExtraToken != ".n") {
5027 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5028 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
5029 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00005030 }
5031
5032 // Read the remaining operands.
5033 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005034 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005035 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00005036 Parser.EatToEndOfStatement();
5037 return true;
5038 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005039
5040 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00005041 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005042
5043 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005044 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00005045 Parser.EatToEndOfStatement();
5046 return true;
5047 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005048 }
5049 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005050
Chris Lattnera2a9d162010-09-11 16:18:25 +00005051 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00005052 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00005053 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00005054 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00005055 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00005056
Chris Lattner91689c12010-09-08 05:10:46 +00005057 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005058
Jim Grosbach7283da92011-08-16 21:12:37 +00005059 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5060 // do and don't have a cc_out optional-def operand. With some spot-checks
5061 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005062 // parse and adjust accordingly before actually matching. We shouldn't ever
5063 // try to remove a cc_out operand that was explicitly set on the the
5064 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5065 // table driven matcher doesn't fit well with the ARM instruction set.
5066 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005067 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5068 Operands.erase(Operands.begin() + 1);
5069 delete Op;
5070 }
5071
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005072 // ARM mode 'blx' need special handling, as the register operand version
5073 // is predicable, but the label operand version is not. So, we can't rely
5074 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00005075 // a k_CondCode operand in the list. If we're trying to match the label
5076 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005077 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5078 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5079 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5080 Operands.erase(Operands.begin() + 1);
5081 delete Op;
5082 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00005083
5084 // The vector-compare-to-zero instructions have a literal token "#0" at
5085 // the end that comes to here as an immediate operand. Convert it to a
5086 // token to play nicely with the matcher.
5087 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5088 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5089 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5090 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5091 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5092 if (CE && CE->getValue() == 0) {
5093 Operands.erase(Operands.begin() + 5);
5094 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5095 delete Op;
5096 }
5097 }
Jim Grosbach46b66462011-10-03 22:30:24 +00005098 // VCMP{E} does the same thing, but with a different operand count.
5099 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5100 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5101 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5102 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5103 if (CE && CE->getValue() == 0) {
5104 Operands.erase(Operands.begin() + 4);
5105 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5106 delete Op;
5107 }
5108 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005109 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005110 // end. Convert it to a token here. Take care not to convert those
5111 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005112 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005113 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5114 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005115 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5116 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5117 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005118 if (CE && CE->getValue() == 0 &&
5119 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00005120 // The cc_out operand matches the IT block.
5121 ((inITBlock() != CarrySetting) &&
5122 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005123 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00005124 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005125 Operands.erase(Operands.begin() + 5);
5126 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5127 delete Op;
5128 }
5129 }
5130
Chris Lattnerf29c0b62010-01-14 22:21:20 +00005131 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00005132}
5133
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005134// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005135
5136// return 'true' if register list contains non-low GPR registers,
5137// 'false' otherwise. If Reg is in the register list or is HiReg, set
5138// 'containsReg' to true.
5139static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5140 unsigned HiReg, bool &containsReg) {
5141 containsReg = false;
5142 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5143 unsigned OpReg = Inst.getOperand(i).getReg();
5144 if (OpReg == Reg)
5145 containsReg = true;
5146 // Anything other than a low register isn't legal here.
5147 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5148 return true;
5149 }
5150 return false;
5151}
5152
Jim Grosbacha31f2232011-09-07 18:05:34 +00005153// Check if the specified regisgter is in the register list of the inst,
5154// starting at the indicated operand number.
5155static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5156 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5157 unsigned OpReg = Inst.getOperand(i).getReg();
5158 if (OpReg == Reg)
5159 return true;
5160 }
5161 return false;
5162}
5163
Jim Grosbached16ec42011-08-29 22:24:09 +00005164// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5165// the ARMInsts array) instead. Getting that here requires awkward
5166// API changes, though. Better way?
5167namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005168extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00005169}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005170static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005171 return ARMInsts[Opcode];
5172}
5173
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005174// FIXME: We would really like to be able to tablegen'erate this.
5175bool ARMAsmParser::
5176validateInstruction(MCInst &Inst,
5177 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005178 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00005179 SMLoc Loc = Operands[0]->getStartLoc();
5180 // Check the IT block state first.
Jim Grosbach82f76d12012-01-25 19:52:01 +00005181 // NOTE: BKPT instruction has the interesting property of being
5182 // allowed in IT blocks, but not being predicable. It just always
Owen Anderson44ae2da2011-09-13 17:59:19 +00005183 // executes.
Jim Grosbach82f76d12012-01-25 19:52:01 +00005184 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5185 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005186 unsigned bit = 1;
5187 if (ITState.FirstCond)
5188 ITState.FirstCond = false;
5189 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005190 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00005191 // The instruction must be predicable.
5192 if (!MCID.isPredicable())
5193 return Error(Loc, "instructions in IT block must be predicable");
5194 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5195 unsigned ITCond = bit ? ITState.Cond :
5196 ARMCC::getOppositeCondition(ITState.Cond);
5197 if (Cond != ITCond) {
5198 // Find the condition code Operand to get its SMLoc information.
5199 SMLoc CondLoc;
5200 for (unsigned i = 1; i < Operands.size(); ++i)
5201 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5202 CondLoc = Operands[i]->getStartLoc();
5203 return Error(CondLoc, "incorrect condition in IT block; got '" +
5204 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5205 "', but expected '" +
5206 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5207 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00005208 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005209 } else if (isThumbTwo() && MCID.isPredicable() &&
5210 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005211 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5212 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00005213 return Error(Loc, "predicated instructions must be in IT block");
5214
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005215 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00005216 case ARM::LDRD:
5217 case ARM::LDRD_PRE:
5218 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005219 case ARM::LDREXD: {
5220 // Rt2 must be Rt + 1.
5221 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5222 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5223 if (Rt2 != Rt + 1)
5224 return Error(Operands[3]->getStartLoc(),
5225 "destination operands must be sequential");
5226 return false;
5227 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00005228 case ARM::STRD: {
5229 // Rt2 must be Rt + 1.
5230 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5231 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5232 if (Rt2 != Rt + 1)
5233 return Error(Operands[3]->getStartLoc(),
5234 "source operands must be sequential");
5235 return false;
5236 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00005237 case ARM::STRD_PRE:
5238 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005239 case ARM::STREXD: {
5240 // Rt2 must be Rt + 1.
5241 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5242 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5243 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00005244 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005245 "source operands must be sequential");
5246 return false;
5247 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00005248 case ARM::SBFX:
5249 case ARM::UBFX: {
5250 // width must be in range [1, 32-lsb]
5251 unsigned lsb = Inst.getOperand(2).getImm();
5252 unsigned widthm1 = Inst.getOperand(3).getImm();
5253 if (widthm1 >= 32 - lsb)
5254 return Error(Operands[5]->getStartLoc(),
5255 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00005256 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00005257 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00005258 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00005259 // If we're parsing Thumb2, the .w variant is available and handles
5260 // most cases that are normally illegal for a Thumb1 LDM
5261 // instruction. We'll make the transformation in processInstruction()
5262 // if necessary.
5263 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00005264 // Thumb LDM instructions are writeback iff the base register is not
5265 // in the register list.
5266 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00005267 bool hasWritebackToken =
5268 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5269 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00005270 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005271 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005272 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5273 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005274 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00005275 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00005276 return Error(Operands[2]->getStartLoc(),
5277 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00005278 // If we should not have writeback, there must not be a '!'. This is
5279 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005280 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00005281 return Error(Operands[3]->getStartLoc(),
5282 "writeback operator '!' not allowed when base register "
5283 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005284
5285 break;
5286 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00005287 case ARM::t2LDMIA_UPD: {
5288 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5289 return Error(Operands[4]->getStartLoc(),
5290 "writeback operator '!' not allowed when base register "
5291 "in register list");
5292 break;
5293 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005294 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5295 // so only issue a diagnostic for thumb1. The instructions will be
5296 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005297 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005298 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005299 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5300 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005301 return Error(Operands[2]->getStartLoc(),
5302 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005303 break;
5304 }
5305 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005306 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005307 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5308 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005309 return Error(Operands[2]->getStartLoc(),
5310 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005311 break;
5312 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00005313 case ARM::tSTMIA_UPD: {
5314 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00005315 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00005316 return Error(Operands[4]->getStartLoc(),
5317 "registers must be in range r0-r7");
5318 break;
5319 }
Jim Grosbachc6f32b32012-04-27 23:51:36 +00005320 case ARM::tADDrSP: {
5321 // If the non-SP source operand and the destination operand are not the
5322 // same, we need thumb2 (for the wide encoding), or we have an error.
5323 if (!isThumbTwo() &&
5324 Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
5325 return Error(Operands[4]->getStartLoc(),
5326 "source register must be the same as destination");
5327 }
5328 break;
5329 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005330 }
5331
5332 return false;
5333}
5334
Jim Grosbach1a747242012-01-23 23:45:44 +00005335static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbacheb538222011-12-02 22:34:51 +00005336 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00005337 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005338 // VST1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005339 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5340 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5341 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5342 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5343 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5344 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5345 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5346 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5347 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005348
5349 // VST2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005350 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5351 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5352 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5353 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5354 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005355
Jim Grosbach1e946a42012-01-24 00:43:12 +00005356 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5357 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5358 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5359 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5360 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005361
Jim Grosbach1e946a42012-01-24 00:43:12 +00005362 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5363 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5364 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5365 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5366 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbach1a747242012-01-23 23:45:44 +00005367
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005368 // VST3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005369 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5370 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5371 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5372 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5373 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5374 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5375 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5376 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5377 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5378 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5379 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5380 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5381 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5382 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5383 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005384
Jim Grosbach1a747242012-01-23 23:45:44 +00005385 // VST3
Jim Grosbach1e946a42012-01-24 00:43:12 +00005386 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5387 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5388 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5389 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5390 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5391 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5392 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5393 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5394 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5395 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5396 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5397 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5398 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5399 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5400 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5401 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5402 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5403 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbachda70eac2012-01-24 00:58:13 +00005404
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005405 // VST4LN
5406 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5407 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5408 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5409 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5410 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5411 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5412 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5413 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5414 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5415 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5416 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5417 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5418 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5419 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5420 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5421
Jim Grosbachda70eac2012-01-24 00:58:13 +00005422 // VST4
5423 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5424 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5425 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5426 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5427 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5428 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5429 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5430 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5431 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5432 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5433 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5434 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5435 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5436 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5437 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5438 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5439 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5440 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005441 }
5442}
5443
Jim Grosbach1a747242012-01-23 23:45:44 +00005444static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005445 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00005446 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005447 // VLD1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005448 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5449 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5450 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5451 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5452 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5453 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5454 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5455 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5456 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005457
5458 // VLD2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005459 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5460 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5461 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5462 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5463 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5464 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5465 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5466 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5467 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5468 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5469 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5470 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5471 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5472 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5473 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005474
Jim Grosbachb78403c2012-01-24 23:47:04 +00005475 // VLD3DUP
5476 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5477 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5478 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5479 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5480 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5481 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5482 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5483 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5484 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5485 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5486 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5487 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5488 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5489 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5490 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5491 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5492 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5493 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5494
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005495 // VLD3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005496 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5497 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5498 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5499 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5500 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5501 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5502 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5503 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5504 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5505 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5506 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5507 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5508 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5509 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5510 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005511
5512 // VLD3
Jim Grosbach1e946a42012-01-24 00:43:12 +00005513 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5514 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5515 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5516 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5517 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5518 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5519 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5520 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5521 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5522 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5523 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5524 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5525 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5526 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5527 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5528 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5529 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5530 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbached561fc2012-01-24 00:43:17 +00005531
Jim Grosbach14952a02012-01-24 18:37:25 +00005532 // VLD4LN
5533 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5534 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5535 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5536 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5537 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5538 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5539 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5540 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5541 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5542 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5543 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5544 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5545 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5546 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5547 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5548
Jim Grosbach086cbfa2012-01-25 00:01:08 +00005549 // VLD4DUP
5550 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5551 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5552 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5553 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5554 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5555 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5556 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5557 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5558 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5559 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5560 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5561 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5562 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5563 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5564 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5565 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5566 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5567 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5568
Jim Grosbached561fc2012-01-24 00:43:17 +00005569 // VLD4
5570 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5571 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5572 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5573 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5574 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5575 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5576 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5577 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5578 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5579 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5580 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5581 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5582 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5583 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5584 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5585 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5586 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5587 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005588 }
5589}
5590
Jim Grosbachafad0532011-11-10 23:42:14 +00005591bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005592processInstruction(MCInst &Inst,
5593 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5594 switch (Inst.getOpcode()) {
Jim Grosbach94298a92012-01-18 22:46:46 +00005595 // Aliases for alternate PC+imm syntax of LDR instructions.
5596 case ARM::t2LDRpcrel:
5597 Inst.setOpcode(ARM::t2LDRpci);
5598 return true;
5599 case ARM::t2LDRBpcrel:
5600 Inst.setOpcode(ARM::t2LDRBpci);
5601 return true;
5602 case ARM::t2LDRHpcrel:
5603 Inst.setOpcode(ARM::t2LDRHpci);
5604 return true;
5605 case ARM::t2LDRSBpcrel:
5606 Inst.setOpcode(ARM::t2LDRSBpci);
5607 return true;
5608 case ARM::t2LDRSHpcrel:
5609 Inst.setOpcode(ARM::t2LDRSHpci);
5610 return true;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005611 // Handle NEON VST complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005612 case ARM::VST1LNdWB_register_Asm_8:
5613 case ARM::VST1LNdWB_register_Asm_16:
5614 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005615 MCInst TmpInst;
5616 // Shuffle the operands around so the lane index operand is in the
5617 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005618 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005619 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005620 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5621 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5622 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5623 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5624 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5625 TmpInst.addOperand(Inst.getOperand(1)); // lane
5626 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5627 TmpInst.addOperand(Inst.getOperand(6));
5628 Inst = TmpInst;
5629 return true;
5630 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005631
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005632 case ARM::VST2LNdWB_register_Asm_8:
5633 case ARM::VST2LNdWB_register_Asm_16:
5634 case ARM::VST2LNdWB_register_Asm_32:
5635 case ARM::VST2LNqWB_register_Asm_16:
5636 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005637 MCInst TmpInst;
5638 // Shuffle the operands around so the lane index operand is in the
5639 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005640 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005641 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005642 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5643 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5644 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5645 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5646 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005647 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5648 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005649 TmpInst.addOperand(Inst.getOperand(1)); // lane
5650 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5651 TmpInst.addOperand(Inst.getOperand(6));
5652 Inst = TmpInst;
5653 return true;
5654 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005655
5656 case ARM::VST3LNdWB_register_Asm_8:
5657 case ARM::VST3LNdWB_register_Asm_16:
5658 case ARM::VST3LNdWB_register_Asm_32:
5659 case ARM::VST3LNqWB_register_Asm_16:
5660 case ARM::VST3LNqWB_register_Asm_32: {
5661 MCInst TmpInst;
5662 // Shuffle the operands around so the lane index operand is in the
5663 // right place.
5664 unsigned Spacing;
5665 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5666 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5667 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5668 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5669 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5670 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5671 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5672 Spacing));
5673 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5674 Spacing * 2));
5675 TmpInst.addOperand(Inst.getOperand(1)); // lane
5676 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5677 TmpInst.addOperand(Inst.getOperand(6));
5678 Inst = TmpInst;
5679 return true;
5680 }
5681
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005682 case ARM::VST4LNdWB_register_Asm_8:
5683 case ARM::VST4LNdWB_register_Asm_16:
5684 case ARM::VST4LNdWB_register_Asm_32:
5685 case ARM::VST4LNqWB_register_Asm_16:
5686 case ARM::VST4LNqWB_register_Asm_32: {
5687 MCInst TmpInst;
5688 // Shuffle the operands around so the lane index operand is in the
5689 // right place.
5690 unsigned Spacing;
5691 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5692 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5693 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5694 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5695 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5696 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5697 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5698 Spacing));
5699 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5700 Spacing * 2));
5701 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5702 Spacing * 3));
5703 TmpInst.addOperand(Inst.getOperand(1)); // lane
5704 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5705 TmpInst.addOperand(Inst.getOperand(6));
5706 Inst = TmpInst;
5707 return true;
5708 }
5709
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005710 case ARM::VST1LNdWB_fixed_Asm_8:
5711 case ARM::VST1LNdWB_fixed_Asm_16:
5712 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005713 MCInst TmpInst;
5714 // Shuffle the operands around so the lane index operand is in the
5715 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005716 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005717 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005718 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5719 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5720 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5721 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5722 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5723 TmpInst.addOperand(Inst.getOperand(1)); // lane
5724 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5725 TmpInst.addOperand(Inst.getOperand(5));
5726 Inst = TmpInst;
5727 return true;
5728 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005729
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005730 case ARM::VST2LNdWB_fixed_Asm_8:
5731 case ARM::VST2LNdWB_fixed_Asm_16:
5732 case ARM::VST2LNdWB_fixed_Asm_32:
5733 case ARM::VST2LNqWB_fixed_Asm_16:
5734 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005735 MCInst TmpInst;
5736 // Shuffle the operands around so the lane index operand is in the
5737 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005738 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005739 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005740 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5741 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5742 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5743 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5744 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005745 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5746 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005747 TmpInst.addOperand(Inst.getOperand(1)); // lane
5748 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5749 TmpInst.addOperand(Inst.getOperand(5));
5750 Inst = TmpInst;
5751 return true;
5752 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005753
5754 case ARM::VST3LNdWB_fixed_Asm_8:
5755 case ARM::VST3LNdWB_fixed_Asm_16:
5756 case ARM::VST3LNdWB_fixed_Asm_32:
5757 case ARM::VST3LNqWB_fixed_Asm_16:
5758 case ARM::VST3LNqWB_fixed_Asm_32: {
5759 MCInst TmpInst;
5760 // Shuffle the operands around so the lane index operand is in the
5761 // right place.
5762 unsigned Spacing;
5763 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5764 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5765 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5766 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5767 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5768 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5769 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5770 Spacing));
5771 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5772 Spacing * 2));
5773 TmpInst.addOperand(Inst.getOperand(1)); // lane
5774 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5775 TmpInst.addOperand(Inst.getOperand(5));
5776 Inst = TmpInst;
5777 return true;
5778 }
5779
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005780 case ARM::VST4LNdWB_fixed_Asm_8:
5781 case ARM::VST4LNdWB_fixed_Asm_16:
5782 case ARM::VST4LNdWB_fixed_Asm_32:
5783 case ARM::VST4LNqWB_fixed_Asm_16:
5784 case ARM::VST4LNqWB_fixed_Asm_32: {
5785 MCInst TmpInst;
5786 // Shuffle the operands around so the lane index operand is in the
5787 // right place.
5788 unsigned Spacing;
5789 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5790 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5791 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5792 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5793 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5794 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5795 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5796 Spacing));
5797 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5798 Spacing * 2));
5799 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5800 Spacing * 3));
5801 TmpInst.addOperand(Inst.getOperand(1)); // lane
5802 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5803 TmpInst.addOperand(Inst.getOperand(5));
5804 Inst = TmpInst;
5805 return true;
5806 }
5807
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005808 case ARM::VST1LNdAsm_8:
5809 case ARM::VST1LNdAsm_16:
5810 case ARM::VST1LNdAsm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005811 MCInst TmpInst;
5812 // Shuffle the operands around so the lane index operand is in the
5813 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005814 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005815 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005816 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5817 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5818 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5819 TmpInst.addOperand(Inst.getOperand(1)); // lane
5820 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5821 TmpInst.addOperand(Inst.getOperand(5));
5822 Inst = TmpInst;
5823 return true;
5824 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005825
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005826 case ARM::VST2LNdAsm_8:
5827 case ARM::VST2LNdAsm_16:
5828 case ARM::VST2LNdAsm_32:
5829 case ARM::VST2LNqAsm_16:
5830 case ARM::VST2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005831 MCInst TmpInst;
5832 // Shuffle the operands around so the lane index operand is in the
5833 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005834 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005835 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005836 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5837 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5838 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005839 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5840 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005841 TmpInst.addOperand(Inst.getOperand(1)); // lane
5842 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5843 TmpInst.addOperand(Inst.getOperand(5));
5844 Inst = TmpInst;
5845 return true;
5846 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005847
5848 case ARM::VST3LNdAsm_8:
5849 case ARM::VST3LNdAsm_16:
5850 case ARM::VST3LNdAsm_32:
5851 case ARM::VST3LNqAsm_16:
5852 case ARM::VST3LNqAsm_32: {
5853 MCInst TmpInst;
5854 // Shuffle the operands around so the lane index operand is in the
5855 // right place.
5856 unsigned Spacing;
5857 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5858 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5859 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5860 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5861 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5862 Spacing));
5863 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5864 Spacing * 2));
5865 TmpInst.addOperand(Inst.getOperand(1)); // lane
5866 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5867 TmpInst.addOperand(Inst.getOperand(5));
5868 Inst = TmpInst;
5869 return true;
5870 }
5871
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005872 case ARM::VST4LNdAsm_8:
5873 case ARM::VST4LNdAsm_16:
5874 case ARM::VST4LNdAsm_32:
5875 case ARM::VST4LNqAsm_16:
5876 case ARM::VST4LNqAsm_32: {
5877 MCInst TmpInst;
5878 // Shuffle the operands around so the lane index operand is in the
5879 // right place.
5880 unsigned Spacing;
5881 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5882 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5883 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5884 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5885 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5886 Spacing));
5887 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5888 Spacing * 2));
5889 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5890 Spacing * 3));
5891 TmpInst.addOperand(Inst.getOperand(1)); // lane
5892 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5893 TmpInst.addOperand(Inst.getOperand(5));
5894 Inst = TmpInst;
5895 return true;
5896 }
5897
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005898 // Handle NEON VLD complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005899 case ARM::VLD1LNdWB_register_Asm_8:
5900 case ARM::VLD1LNdWB_register_Asm_16:
5901 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005902 MCInst TmpInst;
5903 // Shuffle the operands around so the lane index operand is in the
5904 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005905 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005906 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005907 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5908 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5909 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5910 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5911 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5912 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5913 TmpInst.addOperand(Inst.getOperand(1)); // lane
5914 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5915 TmpInst.addOperand(Inst.getOperand(6));
5916 Inst = TmpInst;
5917 return true;
5918 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005919
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005920 case ARM::VLD2LNdWB_register_Asm_8:
5921 case ARM::VLD2LNdWB_register_Asm_16:
5922 case ARM::VLD2LNdWB_register_Asm_32:
5923 case ARM::VLD2LNqWB_register_Asm_16:
5924 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005925 MCInst TmpInst;
5926 // Shuffle the operands around so the lane index operand is in the
5927 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005928 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005929 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005930 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005931 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5932 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005933 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5934 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5935 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5936 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5937 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005938 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5939 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005940 TmpInst.addOperand(Inst.getOperand(1)); // lane
5941 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5942 TmpInst.addOperand(Inst.getOperand(6));
5943 Inst = TmpInst;
5944 return true;
5945 }
5946
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005947 case ARM::VLD3LNdWB_register_Asm_8:
5948 case ARM::VLD3LNdWB_register_Asm_16:
5949 case ARM::VLD3LNdWB_register_Asm_32:
5950 case ARM::VLD3LNqWB_register_Asm_16:
5951 case ARM::VLD3LNqWB_register_Asm_32: {
5952 MCInst TmpInst;
5953 // Shuffle the operands around so the lane index operand is in the
5954 // right place.
5955 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005956 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005957 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5958 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5959 Spacing));
5960 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005961 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005962 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5963 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5964 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5965 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5966 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5967 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5968 Spacing));
5969 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005970 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005971 TmpInst.addOperand(Inst.getOperand(1)); // lane
5972 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5973 TmpInst.addOperand(Inst.getOperand(6));
5974 Inst = TmpInst;
5975 return true;
5976 }
5977
Jim Grosbach14952a02012-01-24 18:37:25 +00005978 case ARM::VLD4LNdWB_register_Asm_8:
5979 case ARM::VLD4LNdWB_register_Asm_16:
5980 case ARM::VLD4LNdWB_register_Asm_32:
5981 case ARM::VLD4LNqWB_register_Asm_16:
5982 case ARM::VLD4LNqWB_register_Asm_32: {
5983 MCInst TmpInst;
5984 // Shuffle the operands around so the lane index operand is in the
5985 // right place.
5986 unsigned Spacing;
5987 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5988 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5989 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5990 Spacing));
5991 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5992 Spacing * 2));
5993 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5994 Spacing * 3));
5995 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5996 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5997 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5998 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5999 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6000 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6001 Spacing));
6002 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6003 Spacing * 2));
6004 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6005 Spacing * 3));
6006 TmpInst.addOperand(Inst.getOperand(1)); // lane
6007 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6008 TmpInst.addOperand(Inst.getOperand(6));
6009 Inst = TmpInst;
6010 return true;
6011 }
6012
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006013 case ARM::VLD1LNdWB_fixed_Asm_8:
6014 case ARM::VLD1LNdWB_fixed_Asm_16:
6015 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00006016 MCInst TmpInst;
6017 // Shuffle the operands around so the lane index operand is in the
6018 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006019 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006020 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00006021 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6022 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6023 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6024 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6025 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6026 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6027 TmpInst.addOperand(Inst.getOperand(1)); // lane
6028 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6029 TmpInst.addOperand(Inst.getOperand(5));
6030 Inst = TmpInst;
6031 return true;
6032 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006033
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006034 case ARM::VLD2LNdWB_fixed_Asm_8:
6035 case ARM::VLD2LNdWB_fixed_Asm_16:
6036 case ARM::VLD2LNdWB_fixed_Asm_32:
6037 case ARM::VLD2LNqWB_fixed_Asm_16:
6038 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006039 MCInst TmpInst;
6040 // Shuffle the operands around so the lane index operand is in the
6041 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006042 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006043 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006044 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006045 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6046 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006047 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6048 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6049 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6050 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6051 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006052 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6053 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006054 TmpInst.addOperand(Inst.getOperand(1)); // lane
6055 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6056 TmpInst.addOperand(Inst.getOperand(5));
6057 Inst = TmpInst;
6058 return true;
6059 }
6060
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006061 case ARM::VLD3LNdWB_fixed_Asm_8:
6062 case ARM::VLD3LNdWB_fixed_Asm_16:
6063 case ARM::VLD3LNdWB_fixed_Asm_32:
6064 case ARM::VLD3LNqWB_fixed_Asm_16:
6065 case ARM::VLD3LNqWB_fixed_Asm_32: {
6066 MCInst TmpInst;
6067 // Shuffle the operands around so the lane index operand is in the
6068 // right place.
6069 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006070 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006071 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6072 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6073 Spacing));
6074 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006075 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006076 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6077 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6078 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6079 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6080 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6081 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6082 Spacing));
6083 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006084 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006085 TmpInst.addOperand(Inst.getOperand(1)); // lane
6086 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6087 TmpInst.addOperand(Inst.getOperand(5));
6088 Inst = TmpInst;
6089 return true;
6090 }
6091
Jim Grosbach14952a02012-01-24 18:37:25 +00006092 case ARM::VLD4LNdWB_fixed_Asm_8:
6093 case ARM::VLD4LNdWB_fixed_Asm_16:
6094 case ARM::VLD4LNdWB_fixed_Asm_32:
6095 case ARM::VLD4LNqWB_fixed_Asm_16:
6096 case ARM::VLD4LNqWB_fixed_Asm_32: {
6097 MCInst TmpInst;
6098 // Shuffle the operands around so the lane index operand is in the
6099 // right place.
6100 unsigned Spacing;
6101 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6102 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6103 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6104 Spacing));
6105 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6106 Spacing * 2));
6107 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6108 Spacing * 3));
6109 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6110 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6111 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6112 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6113 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6114 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6115 Spacing));
6116 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6117 Spacing * 2));
6118 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6119 Spacing * 3));
6120 TmpInst.addOperand(Inst.getOperand(1)); // lane
6121 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6122 TmpInst.addOperand(Inst.getOperand(5));
6123 Inst = TmpInst;
6124 return true;
6125 }
6126
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006127 case ARM::VLD1LNdAsm_8:
6128 case ARM::VLD1LNdAsm_16:
6129 case ARM::VLD1LNdAsm_32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00006130 MCInst TmpInst;
6131 // Shuffle the operands around so the lane index operand is in the
6132 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006133 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006134 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach04945c42011-12-02 00:35:16 +00006135 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6136 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6137 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6138 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6139 TmpInst.addOperand(Inst.getOperand(1)); // lane
6140 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6141 TmpInst.addOperand(Inst.getOperand(5));
6142 Inst = TmpInst;
6143 return true;
6144 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006145
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006146 case ARM::VLD2LNdAsm_8:
6147 case ARM::VLD2LNdAsm_16:
6148 case ARM::VLD2LNdAsm_32:
6149 case ARM::VLD2LNqAsm_16:
6150 case ARM::VLD2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006151 MCInst TmpInst;
6152 // Shuffle the operands around so the lane index operand is in the
6153 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006154 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006155 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006156 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006157 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6158 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006159 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6160 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6161 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006162 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6163 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006164 TmpInst.addOperand(Inst.getOperand(1)); // lane
6165 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6166 TmpInst.addOperand(Inst.getOperand(5));
6167 Inst = TmpInst;
6168 return true;
6169 }
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006170
6171 case ARM::VLD3LNdAsm_8:
6172 case ARM::VLD3LNdAsm_16:
6173 case ARM::VLD3LNdAsm_32:
6174 case ARM::VLD3LNqAsm_16:
6175 case ARM::VLD3LNqAsm_32: {
6176 MCInst TmpInst;
6177 // Shuffle the operands around so the lane index operand is in the
6178 // right place.
6179 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006180 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006181 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6182 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6183 Spacing));
6184 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006185 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006186 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6187 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6188 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6189 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6190 Spacing));
6191 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006192 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006193 TmpInst.addOperand(Inst.getOperand(1)); // lane
6194 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6195 TmpInst.addOperand(Inst.getOperand(5));
6196 Inst = TmpInst;
6197 return true;
6198 }
6199
Jim Grosbach14952a02012-01-24 18:37:25 +00006200 case ARM::VLD4LNdAsm_8:
6201 case ARM::VLD4LNdAsm_16:
6202 case ARM::VLD4LNdAsm_32:
6203 case ARM::VLD4LNqAsm_16:
6204 case ARM::VLD4LNqAsm_32: {
6205 MCInst TmpInst;
6206 // Shuffle the operands around so the lane index operand is in the
6207 // right place.
6208 unsigned Spacing;
6209 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6210 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6211 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6212 Spacing));
6213 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6214 Spacing * 2));
6215 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6216 Spacing * 3));
6217 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6218 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6219 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6220 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6221 Spacing));
6222 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6223 Spacing * 2));
6224 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6225 Spacing * 3));
6226 TmpInst.addOperand(Inst.getOperand(1)); // lane
6227 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6228 TmpInst.addOperand(Inst.getOperand(5));
6229 Inst = TmpInst;
6230 return true;
6231 }
6232
Jim Grosbachb78403c2012-01-24 23:47:04 +00006233 // VLD3DUP single 3-element structure to all lanes instructions.
6234 case ARM::VLD3DUPdAsm_8:
6235 case ARM::VLD3DUPdAsm_16:
6236 case ARM::VLD3DUPdAsm_32:
6237 case ARM::VLD3DUPqAsm_8:
6238 case ARM::VLD3DUPqAsm_16:
6239 case ARM::VLD3DUPqAsm_32: {
6240 MCInst TmpInst;
6241 unsigned Spacing;
6242 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6243 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6244 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6245 Spacing));
6246 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6247 Spacing * 2));
6248 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6249 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6250 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6251 TmpInst.addOperand(Inst.getOperand(4));
6252 Inst = TmpInst;
6253 return true;
6254 }
6255
6256 case ARM::VLD3DUPdWB_fixed_Asm_8:
6257 case ARM::VLD3DUPdWB_fixed_Asm_16:
6258 case ARM::VLD3DUPdWB_fixed_Asm_32:
6259 case ARM::VLD3DUPqWB_fixed_Asm_8:
6260 case ARM::VLD3DUPqWB_fixed_Asm_16:
6261 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6262 MCInst TmpInst;
6263 unsigned Spacing;
6264 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6265 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6266 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6267 Spacing));
6268 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6269 Spacing * 2));
6270 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6271 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6272 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6273 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6274 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6275 TmpInst.addOperand(Inst.getOperand(4));
6276 Inst = TmpInst;
6277 return true;
6278 }
6279
6280 case ARM::VLD3DUPdWB_register_Asm_8:
6281 case ARM::VLD3DUPdWB_register_Asm_16:
6282 case ARM::VLD3DUPdWB_register_Asm_32:
6283 case ARM::VLD3DUPqWB_register_Asm_8:
6284 case ARM::VLD3DUPqWB_register_Asm_16:
6285 case ARM::VLD3DUPqWB_register_Asm_32: {
6286 MCInst TmpInst;
6287 unsigned Spacing;
6288 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6289 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6290 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6291 Spacing));
6292 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6293 Spacing * 2));
6294 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6295 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6296 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6297 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6298 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6299 TmpInst.addOperand(Inst.getOperand(5));
6300 Inst = TmpInst;
6301 return true;
6302 }
6303
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006304 // VLD3 multiple 3-element structure instructions.
6305 case ARM::VLD3dAsm_8:
6306 case ARM::VLD3dAsm_16:
6307 case ARM::VLD3dAsm_32:
6308 case ARM::VLD3qAsm_8:
6309 case ARM::VLD3qAsm_16:
6310 case ARM::VLD3qAsm_32: {
6311 MCInst TmpInst;
6312 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006313 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006314 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6315 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6316 Spacing));
6317 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6318 Spacing * 2));
6319 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6320 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6321 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6322 TmpInst.addOperand(Inst.getOperand(4));
6323 Inst = TmpInst;
6324 return true;
6325 }
6326
6327 case ARM::VLD3dWB_fixed_Asm_8:
6328 case ARM::VLD3dWB_fixed_Asm_16:
6329 case ARM::VLD3dWB_fixed_Asm_32:
6330 case ARM::VLD3qWB_fixed_Asm_8:
6331 case ARM::VLD3qWB_fixed_Asm_16:
6332 case ARM::VLD3qWB_fixed_Asm_32: {
6333 MCInst TmpInst;
6334 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006335 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006336 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6337 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6338 Spacing));
6339 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6340 Spacing * 2));
6341 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6342 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6343 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6344 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6345 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6346 TmpInst.addOperand(Inst.getOperand(4));
6347 Inst = TmpInst;
6348 return true;
6349 }
6350
6351 case ARM::VLD3dWB_register_Asm_8:
6352 case ARM::VLD3dWB_register_Asm_16:
6353 case ARM::VLD3dWB_register_Asm_32:
6354 case ARM::VLD3qWB_register_Asm_8:
6355 case ARM::VLD3qWB_register_Asm_16:
6356 case ARM::VLD3qWB_register_Asm_32: {
6357 MCInst TmpInst;
6358 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006359 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006360 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6361 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6362 Spacing));
6363 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6364 Spacing * 2));
6365 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6366 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6367 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6368 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6369 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6370 TmpInst.addOperand(Inst.getOperand(5));
6371 Inst = TmpInst;
6372 return true;
6373 }
6374
Jim Grosbach086cbfa2012-01-25 00:01:08 +00006375 // VLD4DUP single 3-element structure to all lanes instructions.
6376 case ARM::VLD4DUPdAsm_8:
6377 case ARM::VLD4DUPdAsm_16:
6378 case ARM::VLD4DUPdAsm_32:
6379 case ARM::VLD4DUPqAsm_8:
6380 case ARM::VLD4DUPqAsm_16:
6381 case ARM::VLD4DUPqAsm_32: {
6382 MCInst TmpInst;
6383 unsigned Spacing;
6384 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6385 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6386 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6387 Spacing));
6388 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6389 Spacing * 2));
6390 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6391 Spacing * 3));
6392 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6393 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6394 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6395 TmpInst.addOperand(Inst.getOperand(4));
6396 Inst = TmpInst;
6397 return true;
6398 }
6399
6400 case ARM::VLD4DUPdWB_fixed_Asm_8:
6401 case ARM::VLD4DUPdWB_fixed_Asm_16:
6402 case ARM::VLD4DUPdWB_fixed_Asm_32:
6403 case ARM::VLD4DUPqWB_fixed_Asm_8:
6404 case ARM::VLD4DUPqWB_fixed_Asm_16:
6405 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6406 MCInst TmpInst;
6407 unsigned Spacing;
6408 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6409 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6410 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6411 Spacing));
6412 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6413 Spacing * 2));
6414 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6415 Spacing * 3));
6416 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6417 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6418 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6419 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6420 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6421 TmpInst.addOperand(Inst.getOperand(4));
6422 Inst = TmpInst;
6423 return true;
6424 }
6425
6426 case ARM::VLD4DUPdWB_register_Asm_8:
6427 case ARM::VLD4DUPdWB_register_Asm_16:
6428 case ARM::VLD4DUPdWB_register_Asm_32:
6429 case ARM::VLD4DUPqWB_register_Asm_8:
6430 case ARM::VLD4DUPqWB_register_Asm_16:
6431 case ARM::VLD4DUPqWB_register_Asm_32: {
6432 MCInst TmpInst;
6433 unsigned Spacing;
6434 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6435 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6436 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6437 Spacing));
6438 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6439 Spacing * 2));
6440 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6441 Spacing * 3));
6442 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6443 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6444 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6445 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6446 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6447 TmpInst.addOperand(Inst.getOperand(5));
6448 Inst = TmpInst;
6449 return true;
6450 }
6451
6452 // VLD4 multiple 4-element structure instructions.
Jim Grosbached561fc2012-01-24 00:43:17 +00006453 case ARM::VLD4dAsm_8:
6454 case ARM::VLD4dAsm_16:
6455 case ARM::VLD4dAsm_32:
6456 case ARM::VLD4qAsm_8:
6457 case ARM::VLD4qAsm_16:
6458 case ARM::VLD4qAsm_32: {
6459 MCInst TmpInst;
6460 unsigned Spacing;
6461 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6462 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6463 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6464 Spacing));
6465 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6466 Spacing * 2));
6467 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6468 Spacing * 3));
6469 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6470 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6471 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6472 TmpInst.addOperand(Inst.getOperand(4));
6473 Inst = TmpInst;
6474 return true;
6475 }
6476
6477 case ARM::VLD4dWB_fixed_Asm_8:
6478 case ARM::VLD4dWB_fixed_Asm_16:
6479 case ARM::VLD4dWB_fixed_Asm_32:
6480 case ARM::VLD4qWB_fixed_Asm_8:
6481 case ARM::VLD4qWB_fixed_Asm_16:
6482 case ARM::VLD4qWB_fixed_Asm_32: {
6483 MCInst TmpInst;
6484 unsigned Spacing;
6485 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6486 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6487 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6488 Spacing));
6489 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6490 Spacing * 2));
6491 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6492 Spacing * 3));
6493 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6494 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6495 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6496 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6497 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6498 TmpInst.addOperand(Inst.getOperand(4));
6499 Inst = TmpInst;
6500 return true;
6501 }
6502
6503 case ARM::VLD4dWB_register_Asm_8:
6504 case ARM::VLD4dWB_register_Asm_16:
6505 case ARM::VLD4dWB_register_Asm_32:
6506 case ARM::VLD4qWB_register_Asm_8:
6507 case ARM::VLD4qWB_register_Asm_16:
6508 case ARM::VLD4qWB_register_Asm_32: {
6509 MCInst TmpInst;
6510 unsigned Spacing;
6511 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6512 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6513 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6514 Spacing));
6515 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6516 Spacing * 2));
6517 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6518 Spacing * 3));
6519 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6520 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6521 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6522 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6523 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6524 TmpInst.addOperand(Inst.getOperand(5));
6525 Inst = TmpInst;
6526 return true;
6527 }
6528
Jim Grosbach1a747242012-01-23 23:45:44 +00006529 // VST3 multiple 3-element structure instructions.
6530 case ARM::VST3dAsm_8:
6531 case ARM::VST3dAsm_16:
6532 case ARM::VST3dAsm_32:
6533 case ARM::VST3qAsm_8:
6534 case ARM::VST3qAsm_16:
6535 case ARM::VST3qAsm_32: {
6536 MCInst TmpInst;
6537 unsigned Spacing;
6538 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6539 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6540 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6541 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6542 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6543 Spacing));
6544 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6545 Spacing * 2));
6546 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6547 TmpInst.addOperand(Inst.getOperand(4));
6548 Inst = TmpInst;
6549 return true;
6550 }
6551
6552 case ARM::VST3dWB_fixed_Asm_8:
6553 case ARM::VST3dWB_fixed_Asm_16:
6554 case ARM::VST3dWB_fixed_Asm_32:
6555 case ARM::VST3qWB_fixed_Asm_8:
6556 case ARM::VST3qWB_fixed_Asm_16:
6557 case ARM::VST3qWB_fixed_Asm_32: {
6558 MCInst TmpInst;
6559 unsigned Spacing;
6560 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6561 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6562 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6563 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6564 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6565 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6566 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6567 Spacing));
6568 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6569 Spacing * 2));
6570 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6571 TmpInst.addOperand(Inst.getOperand(4));
6572 Inst = TmpInst;
6573 return true;
6574 }
6575
6576 case ARM::VST3dWB_register_Asm_8:
6577 case ARM::VST3dWB_register_Asm_16:
6578 case ARM::VST3dWB_register_Asm_32:
6579 case ARM::VST3qWB_register_Asm_8:
6580 case ARM::VST3qWB_register_Asm_16:
6581 case ARM::VST3qWB_register_Asm_32: {
6582 MCInst TmpInst;
6583 unsigned Spacing;
6584 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6585 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6586 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6587 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6588 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6589 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6590 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6591 Spacing));
6592 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6593 Spacing * 2));
6594 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6595 TmpInst.addOperand(Inst.getOperand(5));
6596 Inst = TmpInst;
6597 return true;
6598 }
6599
Jim Grosbachda70eac2012-01-24 00:58:13 +00006600 // VST4 multiple 3-element structure instructions.
6601 case ARM::VST4dAsm_8:
6602 case ARM::VST4dAsm_16:
6603 case ARM::VST4dAsm_32:
6604 case ARM::VST4qAsm_8:
6605 case ARM::VST4qAsm_16:
6606 case ARM::VST4qAsm_32: {
6607 MCInst TmpInst;
6608 unsigned Spacing;
6609 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6610 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6611 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6612 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6613 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6614 Spacing));
6615 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6616 Spacing * 2));
6617 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6618 Spacing * 3));
6619 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6620 TmpInst.addOperand(Inst.getOperand(4));
6621 Inst = TmpInst;
6622 return true;
6623 }
6624
6625 case ARM::VST4dWB_fixed_Asm_8:
6626 case ARM::VST4dWB_fixed_Asm_16:
6627 case ARM::VST4dWB_fixed_Asm_32:
6628 case ARM::VST4qWB_fixed_Asm_8:
6629 case ARM::VST4qWB_fixed_Asm_16:
6630 case ARM::VST4qWB_fixed_Asm_32: {
6631 MCInst TmpInst;
6632 unsigned Spacing;
6633 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6634 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6635 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6636 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6637 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6638 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6639 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6640 Spacing));
6641 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6642 Spacing * 2));
6643 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6644 Spacing * 3));
6645 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6646 TmpInst.addOperand(Inst.getOperand(4));
6647 Inst = TmpInst;
6648 return true;
6649 }
6650
6651 case ARM::VST4dWB_register_Asm_8:
6652 case ARM::VST4dWB_register_Asm_16:
6653 case ARM::VST4dWB_register_Asm_32:
6654 case ARM::VST4qWB_register_Asm_8:
6655 case ARM::VST4qWB_register_Asm_16:
6656 case ARM::VST4qWB_register_Asm_32: {
6657 MCInst TmpInst;
6658 unsigned Spacing;
6659 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6660 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6661 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6662 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6663 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6664 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6665 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6666 Spacing));
6667 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6668 Spacing * 2));
6669 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6670 Spacing * 3));
6671 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6672 TmpInst.addOperand(Inst.getOperand(5));
6673 Inst = TmpInst;
6674 return true;
6675 }
6676
Jim Grosbachad66de12012-04-11 00:15:16 +00006677 // Handle encoding choice for the shift-immediate instructions.
6678 case ARM::t2LSLri:
6679 case ARM::t2LSRri:
6680 case ARM::t2ASRri: {
6681 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6682 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6683 Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
6684 !(static_cast<ARMOperand*>(Operands[3])->isToken() &&
6685 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) {
6686 unsigned NewOpc;
6687 switch (Inst.getOpcode()) {
6688 default: llvm_unreachable("unexpected opcode");
6689 case ARM::t2LSLri: NewOpc = ARM::tLSLri; break;
6690 case ARM::t2LSRri: NewOpc = ARM::tLSRri; break;
6691 case ARM::t2ASRri: NewOpc = ARM::tASRri; break;
6692 }
6693 // The Thumb1 operands aren't in the same order. Awesome, eh?
6694 MCInst TmpInst;
6695 TmpInst.setOpcode(NewOpc);
6696 TmpInst.addOperand(Inst.getOperand(0));
6697 TmpInst.addOperand(Inst.getOperand(5));
6698 TmpInst.addOperand(Inst.getOperand(1));
6699 TmpInst.addOperand(Inst.getOperand(2));
6700 TmpInst.addOperand(Inst.getOperand(3));
6701 TmpInst.addOperand(Inst.getOperand(4));
6702 Inst = TmpInst;
6703 return true;
6704 }
6705 return false;
6706 }
6707
Jim Grosbach485e5622011-12-13 22:45:11 +00006708 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbachb3ef7132011-12-21 20:54:00 +00006709 case ARM::t2MOVsr:
6710 case ARM::t2MOVSsr: {
6711 // Which instruction to expand to depends on the CCOut operand and
6712 // whether we're in an IT block if the register operands are low
6713 // registers.
6714 bool isNarrow = false;
6715 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6716 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6717 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6718 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6719 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6720 isNarrow = true;
6721 MCInst TmpInst;
6722 unsigned newOpc;
6723 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6724 default: llvm_unreachable("unexpected opcode!");
6725 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6726 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6727 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6728 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6729 }
6730 TmpInst.setOpcode(newOpc);
6731 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6732 if (isNarrow)
6733 TmpInst.addOperand(MCOperand::CreateReg(
6734 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6735 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6736 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6737 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6738 TmpInst.addOperand(Inst.getOperand(5));
6739 if (!isNarrow)
6740 TmpInst.addOperand(MCOperand::CreateReg(
6741 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6742 Inst = TmpInst;
6743 return true;
6744 }
Jim Grosbach485e5622011-12-13 22:45:11 +00006745 case ARM::t2MOVsi:
6746 case ARM::t2MOVSsi: {
6747 // Which instruction to expand to depends on the CCOut operand and
6748 // whether we're in an IT block if the register operands are low
6749 // registers.
6750 bool isNarrow = false;
6751 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6752 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6753 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6754 isNarrow = true;
6755 MCInst TmpInst;
6756 unsigned newOpc;
6757 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6758 default: llvm_unreachable("unexpected opcode!");
6759 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6760 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6761 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6762 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00006763 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach485e5622011-12-13 22:45:11 +00006764 }
6765 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6766 if (Ammount == 32) Ammount = 0;
6767 TmpInst.setOpcode(newOpc);
6768 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6769 if (isNarrow)
6770 TmpInst.addOperand(MCOperand::CreateReg(
6771 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6772 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00006773 if (newOpc != ARM::t2RRX)
6774 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach485e5622011-12-13 22:45:11 +00006775 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6776 TmpInst.addOperand(Inst.getOperand(4));
6777 if (!isNarrow)
6778 TmpInst.addOperand(MCOperand::CreateReg(
6779 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6780 Inst = TmpInst;
6781 return true;
6782 }
6783 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00006784 case ARM::ASRr:
6785 case ARM::LSRr:
6786 case ARM::LSLr:
6787 case ARM::RORr: {
6788 ARM_AM::ShiftOpc ShiftTy;
6789 switch(Inst.getOpcode()) {
6790 default: llvm_unreachable("unexpected opcode!");
6791 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6792 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6793 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6794 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6795 }
Jim Grosbachabcac562011-11-16 18:31:45 +00006796 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6797 MCInst TmpInst;
6798 TmpInst.setOpcode(ARM::MOVsr);
6799 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6800 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6801 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6802 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6803 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6804 TmpInst.addOperand(Inst.getOperand(4));
6805 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6806 Inst = TmpInst;
6807 return true;
6808 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00006809 case ARM::ASRi:
6810 case ARM::LSRi:
6811 case ARM::LSLi:
6812 case ARM::RORi: {
6813 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00006814 switch(Inst.getOpcode()) {
6815 default: llvm_unreachable("unexpected opcode!");
6816 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6817 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6818 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6819 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6820 }
6821 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00006822 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00006823 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
Richard Bartonba5b0cc2012-04-25 18:00:18 +00006824 // A shift by 32 should be encoded as 0 when permitted
6825 if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr))
6826 Amt = 0;
Jim Grosbachc14871c2011-11-10 19:18:01 +00006827 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00006828 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00006829 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00006830 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6831 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00006832 if (Opc == ARM::MOVsi)
6833 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00006834 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6835 TmpInst.addOperand(Inst.getOperand(4));
6836 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6837 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006838 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00006839 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00006840 case ARM::RRXi: {
6841 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6842 MCInst TmpInst;
6843 TmpInst.setOpcode(ARM::MOVsi);
6844 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6845 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6846 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6847 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6848 TmpInst.addOperand(Inst.getOperand(3));
6849 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6850 Inst = TmpInst;
6851 return true;
6852 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00006853 case ARM::t2LDMIA_UPD: {
6854 // If this is a load of a single register, then we should use
6855 // a post-indexed LDR instruction instead, per the ARM ARM.
6856 if (Inst.getNumOperands() != 5)
6857 return false;
6858 MCInst TmpInst;
6859 TmpInst.setOpcode(ARM::t2LDR_POST);
6860 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6861 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6862 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6863 TmpInst.addOperand(MCOperand::CreateImm(4));
6864 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6865 TmpInst.addOperand(Inst.getOperand(3));
6866 Inst = TmpInst;
6867 return true;
6868 }
6869 case ARM::t2STMDB_UPD: {
6870 // If this is a store of a single register, then we should use
6871 // a pre-indexed STR instruction instead, per the ARM ARM.
6872 if (Inst.getNumOperands() != 5)
6873 return false;
6874 MCInst TmpInst;
6875 TmpInst.setOpcode(ARM::t2STR_PRE);
6876 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6877 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6878 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6879 TmpInst.addOperand(MCOperand::CreateImm(-4));
6880 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6881 TmpInst.addOperand(Inst.getOperand(3));
6882 Inst = TmpInst;
6883 return true;
6884 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006885 case ARM::LDMIA_UPD:
6886 // If this is a load of a single register via a 'pop', then we should use
6887 // a post-indexed LDR instruction instead, per the ARM ARM.
6888 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6889 Inst.getNumOperands() == 5) {
6890 MCInst TmpInst;
6891 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6892 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6893 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6894 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6895 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6896 TmpInst.addOperand(MCOperand::CreateImm(4));
6897 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6898 TmpInst.addOperand(Inst.getOperand(3));
6899 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006900 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006901 }
6902 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00006903 case ARM::STMDB_UPD:
6904 // If this is a store of a single register via a 'push', then we should use
6905 // a pre-indexed STR instruction instead, per the ARM ARM.
6906 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6907 Inst.getNumOperands() == 5) {
6908 MCInst TmpInst;
6909 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6910 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6911 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6912 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6913 TmpInst.addOperand(MCOperand::CreateImm(-4));
6914 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6915 TmpInst.addOperand(Inst.getOperand(3));
6916 Inst = TmpInst;
6917 }
6918 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00006919 case ARM::t2ADDri12:
6920 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6921 // mnemonic was used (not "addw"), encoding T3 is preferred.
6922 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6923 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6924 break;
6925 Inst.setOpcode(ARM::t2ADDri);
6926 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6927 break;
6928 case ARM::t2SUBri12:
6929 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6930 // mnemonic was used (not "subw"), encoding T3 is preferred.
6931 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6932 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6933 break;
6934 Inst.setOpcode(ARM::t2SUBri);
6935 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6936 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006937 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00006938 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6939 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6940 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6941 // to encoding T1 if <Rd> is omitted."
Jim Grosbach199ab902012-03-30 16:31:31 +00006942 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006943 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006944 return true;
6945 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006946 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006947 case ARM::tSUBi8:
6948 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6949 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6950 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6951 // to encoding T1 if <Rd> is omitted."
Jim Grosbach199ab902012-03-30 16:31:31 +00006952 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006953 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006954 return true;
6955 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006956 break;
Jim Grosbachdef5e342012-03-30 17:20:40 +00006957 case ARM::t2ADDri:
6958 case ARM::t2SUBri: {
6959 // If the destination and first source operand are the same, and
6960 // the flags are compatible with the current IT status, use encoding T2
6961 // instead of T3. For compatibility with the system 'as'. Make sure the
6962 // wide encoding wasn't explicit.
6963 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
Jim Grosbach74005ae2012-03-30 18:39:43 +00006964 !isARMLowRegister(Inst.getOperand(0).getReg()) ||
Jim Grosbachdef5e342012-03-30 17:20:40 +00006965 (unsigned)Inst.getOperand(2).getImm() > 255 ||
6966 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
6967 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
6968 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6969 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
6970 break;
6971 MCInst TmpInst;
6972 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
6973 ARM::tADDi8 : ARM::tSUBi8);
6974 TmpInst.addOperand(Inst.getOperand(0));
6975 TmpInst.addOperand(Inst.getOperand(5));
6976 TmpInst.addOperand(Inst.getOperand(0));
6977 TmpInst.addOperand(Inst.getOperand(2));
6978 TmpInst.addOperand(Inst.getOperand(3));
6979 TmpInst.addOperand(Inst.getOperand(4));
6980 Inst = TmpInst;
6981 return true;
6982 }
Jim Grosbache489bab2011-12-05 22:16:39 +00006983 case ARM::t2ADDrr: {
6984 // If the destination and first source operand are the same, and
6985 // there's no setting of the flags, use encoding T2 instead of T3.
6986 // Note that this is only for ADD, not SUB. This mirrors the system
6987 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6988 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6989 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00006990 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6991 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00006992 break;
6993 MCInst TmpInst;
6994 TmpInst.setOpcode(ARM::tADDhirr);
6995 TmpInst.addOperand(Inst.getOperand(0));
6996 TmpInst.addOperand(Inst.getOperand(0));
6997 TmpInst.addOperand(Inst.getOperand(2));
6998 TmpInst.addOperand(Inst.getOperand(3));
6999 TmpInst.addOperand(Inst.getOperand(4));
7000 Inst = TmpInst;
7001 return true;
7002 }
Jim Grosbachc6f32b32012-04-27 23:51:36 +00007003 case ARM::tADDrSP: {
7004 // If the non-SP source operand and the destination operand are not the
7005 // same, we need to use the 32-bit encoding if it's available.
7006 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
7007 Inst.setOpcode(ARM::t2ADDrr);
7008 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7009 return true;
7010 }
7011 break;
7012 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007013 case ARM::tB:
7014 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00007015 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007016 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00007017 return true;
7018 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007019 break;
7020 case ARM::t2B:
7021 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00007022 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007023 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00007024 return true;
7025 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007026 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00007027 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007028 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00007029 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00007030 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00007031 return true;
7032 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00007033 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00007034 case ARM::tBcc:
7035 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00007036 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00007037 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00007038 return true;
7039 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00007040 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00007041 case ARM::tLDMIA: {
7042 // If the register list contains any high registers, or if the writeback
7043 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
7044 // instead if we're in Thumb2. Otherwise, this should have generated
7045 // an error in validateInstruction().
7046 unsigned Rn = Inst.getOperand(0).getReg();
7047 bool hasWritebackToken =
7048 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7049 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
7050 bool listContainsBase;
7051 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
7052 (!listContainsBase && !hasWritebackToken) ||
7053 (listContainsBase && hasWritebackToken)) {
7054 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7055 assert (isThumbTwo());
7056 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
7057 // If we're switching to the updating version, we need to insert
7058 // the writeback tied operand.
7059 if (hasWritebackToken)
7060 Inst.insert(Inst.begin(),
7061 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00007062 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00007063 }
7064 break;
7065 }
Jim Grosbach099c9762011-09-16 20:50:13 +00007066 case ARM::tSTMIA_UPD: {
7067 // If the register list contains any high registers, we need to use
7068 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7069 // should have generated an error in validateInstruction().
7070 unsigned Rn = Inst.getOperand(0).getReg();
7071 bool listContainsBase;
7072 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
7073 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7074 assert (isThumbTwo());
7075 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00007076 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00007077 }
7078 break;
7079 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007080 case ARM::tPOP: {
7081 bool listContainsBase;
7082 // If the register list contains any high registers, we need to use
7083 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7084 // should have generated an error in validateInstruction().
7085 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00007086 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007087 assert (isThumbTwo());
7088 Inst.setOpcode(ARM::t2LDMIA_UPD);
7089 // Add the base register and writeback operands.
7090 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7091 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00007092 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007093 }
7094 case ARM::tPUSH: {
7095 bool listContainsBase;
7096 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00007097 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007098 assert (isThumbTwo());
7099 Inst.setOpcode(ARM::t2STMDB_UPD);
7100 // Add the base register and writeback operands.
7101 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7102 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00007103 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007104 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00007105 case ARM::t2MOVi: {
7106 // If we can use the 16-bit encoding and the user didn't explicitly
7107 // request the 32-bit variant, transform it here.
7108 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbach199ab902012-03-30 16:31:31 +00007109 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00007110 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
7111 Inst.getOperand(4).getReg() == ARM::CPSR) ||
7112 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00007113 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7114 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7115 // The operands aren't in the same order for tMOVi8...
7116 MCInst TmpInst;
7117 TmpInst.setOpcode(ARM::tMOVi8);
7118 TmpInst.addOperand(Inst.getOperand(0));
7119 TmpInst.addOperand(Inst.getOperand(4));
7120 TmpInst.addOperand(Inst.getOperand(1));
7121 TmpInst.addOperand(Inst.getOperand(2));
7122 TmpInst.addOperand(Inst.getOperand(3));
7123 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007124 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00007125 }
7126 break;
7127 }
7128 case ARM::t2MOVr: {
7129 // If we can use the 16-bit encoding and the user didn't explicitly
7130 // request the 32-bit variant, transform it here.
7131 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7132 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7133 Inst.getOperand(2).getImm() == ARMCC::AL &&
7134 Inst.getOperand(4).getReg() == ARM::CPSR &&
7135 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7136 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7137 // The operands aren't the same for tMOV[S]r... (no cc_out)
7138 MCInst TmpInst;
7139 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7140 TmpInst.addOperand(Inst.getOperand(0));
7141 TmpInst.addOperand(Inst.getOperand(1));
7142 TmpInst.addOperand(Inst.getOperand(2));
7143 TmpInst.addOperand(Inst.getOperand(3));
7144 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007145 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00007146 }
7147 break;
7148 }
Jim Grosbach82213192011-09-19 20:29:33 +00007149 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00007150 case ARM::t2SXTB:
7151 case ARM::t2UXTH:
7152 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00007153 // If we can use the 16-bit encoding and the user didn't explicitly
7154 // request the 32-bit variant, transform it here.
7155 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7156 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7157 Inst.getOperand(2).getImm() == 0 &&
7158 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7159 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00007160 unsigned NewOpc;
7161 switch (Inst.getOpcode()) {
7162 default: llvm_unreachable("Illegal opcode!");
7163 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7164 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7165 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7166 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7167 }
Jim Grosbach82213192011-09-19 20:29:33 +00007168 // The operands aren't the same for thumb1 (no rotate operand).
7169 MCInst TmpInst;
7170 TmpInst.setOpcode(NewOpc);
7171 TmpInst.addOperand(Inst.getOperand(0));
7172 TmpInst.addOperand(Inst.getOperand(1));
7173 TmpInst.addOperand(Inst.getOperand(3));
7174 TmpInst.addOperand(Inst.getOperand(4));
7175 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007176 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00007177 }
7178 break;
7179 }
Jim Grosbache2ca9e52011-12-20 00:59:38 +00007180 case ARM::MOVsi: {
7181 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
Richard Bartonba5b0cc2012-04-25 18:00:18 +00007182 // rrx shifts and asr/lsr of #32 is encoded as 0
7183 if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr)
7184 return false;
Jim Grosbache2ca9e52011-12-20 00:59:38 +00007185 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7186 // Shifting by zero is accepted as a vanilla 'MOVr'
7187 MCInst TmpInst;
7188 TmpInst.setOpcode(ARM::MOVr);
7189 TmpInst.addOperand(Inst.getOperand(0));
7190 TmpInst.addOperand(Inst.getOperand(1));
7191 TmpInst.addOperand(Inst.getOperand(3));
7192 TmpInst.addOperand(Inst.getOperand(4));
7193 TmpInst.addOperand(Inst.getOperand(5));
7194 Inst = TmpInst;
7195 return true;
7196 }
7197 return false;
7198 }
Jim Grosbach12ccf452011-12-22 18:04:04 +00007199 case ARM::ANDrsi:
7200 case ARM::ORRrsi:
7201 case ARM::EORrsi:
7202 case ARM::BICrsi:
7203 case ARM::SUBrsi:
7204 case ARM::ADDrsi: {
7205 unsigned newOpc;
7206 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7207 if (SOpc == ARM_AM::rrx) return false;
7208 switch (Inst.getOpcode()) {
Craig Toppere55c5562012-02-07 02:50:20 +00007209 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach12ccf452011-12-22 18:04:04 +00007210 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7211 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7212 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7213 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7214 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7215 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7216 }
7217 // If the shift is by zero, use the non-shifted instruction definition.
7218 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7219 MCInst TmpInst;
7220 TmpInst.setOpcode(newOpc);
7221 TmpInst.addOperand(Inst.getOperand(0));
7222 TmpInst.addOperand(Inst.getOperand(1));
7223 TmpInst.addOperand(Inst.getOperand(2));
7224 TmpInst.addOperand(Inst.getOperand(4));
7225 TmpInst.addOperand(Inst.getOperand(5));
7226 TmpInst.addOperand(Inst.getOperand(6));
7227 Inst = TmpInst;
7228 return true;
7229 }
7230 return false;
7231 }
Jim Grosbach82f76d12012-01-25 19:52:01 +00007232 case ARM::ITasm:
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007233 case ARM::t2IT: {
7234 // The mask bits for all but the first condition are represented as
7235 // the low bit of the condition code value implies 't'. We currently
7236 // always have 1 implies 't', so XOR toggle the bits if the low bit
Richard Bartonf435b092012-04-27 08:42:59 +00007237 // of the condition code is zero.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007238 MCOperand &MO = Inst.getOperand(1);
7239 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00007240 unsigned OrigMask = Mask;
7241 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007242 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007243 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7244 for (unsigned i = 3; i != TZ; --i)
7245 Mask ^= 1 << i;
Richard Bartonf435b092012-04-27 08:42:59 +00007246 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007247 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00007248
7249 // Set up the IT block state according to the IT instruction we just
7250 // matched.
7251 assert(!inITBlock() && "nested IT blocks?!");
7252 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7253 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7254 ITState.CurPosition = 0;
7255 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007256 break;
7257 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007258 }
Jim Grosbachafad0532011-11-10 23:42:14 +00007259 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007260}
7261
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007262unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7263 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7264 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007265 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00007266 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007267 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7268 assert(MCID.hasOptionalDef() &&
7269 "optionally flag setting instruction missing optional def operand");
7270 assert(MCID.NumOperands == Inst.getNumOperands() &&
7271 "operand count mismatch!");
7272 // Find the optional-def operand (cc_out).
7273 unsigned OpNo;
7274 for (OpNo = 0;
7275 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7276 ++OpNo)
7277 ;
7278 // If we're parsing Thumb1, reject it completely.
7279 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7280 return Match_MnemonicFail;
7281 // If we're parsing Thumb2, which form is legal depends on whether we're
7282 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00007283 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7284 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007285 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00007286 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7287 inITBlock())
7288 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007289 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007290 // Some high-register supporting Thumb1 encodings only allow both registers
7291 // to be from r0-r7 when in Thumb2.
7292 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7293 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7294 isARMLowRegister(Inst.getOperand(2).getReg()))
7295 return Match_RequiresThumb2;
7296 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00007297 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007298 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7299 isARMLowRegister(Inst.getOperand(1).getReg()))
7300 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007301 return Match_Success;
7302}
7303
Jim Grosbach5117ef72012-04-24 22:40:08 +00007304static const char *getSubtargetFeatureName(unsigned Val);
Chris Lattner9487de62010-10-28 21:28:01 +00007305bool ARMAsmParser::
7306MatchAndEmitInstruction(SMLoc IDLoc,
7307 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7308 MCStreamer &Out) {
7309 MCInst Inst;
7310 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00007311 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00007312 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00007313 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00007314 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007315 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007316 // Context sensitive operand constraints aren't handled by the matcher,
7317 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007318 if (validateInstruction(Inst, Operands)) {
7319 // Still progress the IT block, otherwise one wrong condition causes
7320 // nasty cascading errors.
7321 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007322 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007323 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007324
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007325 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00007326 // encoding is selected. Loop on it while changes happen so the
7327 // individual transformations can chain off each other. E.g.,
7328 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7329 while (processInstruction(Inst, Operands))
7330 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007331
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007332 // Only move forward at the very end so that everything in validate
7333 // and process gets a consistent answer about whether we're in an IT
7334 // block.
7335 forwardITPosition();
7336
Jim Grosbach82f76d12012-01-25 19:52:01 +00007337 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7338 // doesn't actually encode.
7339 if (Inst.getOpcode() == ARM::ITasm)
7340 return false;
7341
Jim Grosbach5e5eabb2012-01-26 23:20:15 +00007342 Inst.setLoc(IDLoc);
Chris Lattner9487de62010-10-28 21:28:01 +00007343 Out.EmitInstruction(Inst);
7344 return false;
Jim Grosbach5117ef72012-04-24 22:40:08 +00007345 case Match_MissingFeature: {
7346 assert(ErrorInfo && "Unknown missing feature!");
7347 // Special case the error message for the very common case where only
7348 // a single subtarget feature is missing (Thumb vs. ARM, e.g.).
7349 std::string Msg = "instruction requires:";
7350 unsigned Mask = 1;
7351 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
7352 if (ErrorInfo & Mask) {
7353 Msg += " ";
7354 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
7355 }
7356 Mask <<= 1;
7357 }
7358 return Error(IDLoc, Msg);
7359 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007360 case Match_InvalidOperand: {
7361 SMLoc ErrorLoc = IDLoc;
7362 if (ErrorInfo != ~0U) {
7363 if (ErrorInfo >= Operands.size())
7364 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00007365
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007366 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7367 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7368 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00007369
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007370 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00007371 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007372 case Match_MnemonicFail:
Benjamin Kramer673824b2012-04-15 17:04:27 +00007373 return Error(IDLoc, "invalid instruction",
7374 ((ARMOperand*)Operands[0])->getLocRange());
Daniel Dunbar66193402011-02-04 17:12:23 +00007375 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00007376 // The converter function will have already emited a diagnostic.
7377 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00007378 case Match_RequiresNotITBlock:
7379 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007380 case Match_RequiresITBlock:
7381 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007382 case Match_RequiresV6:
7383 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7384 case Match_RequiresThumb2:
7385 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007386 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00007387
Eric Christopher91d7b902010-10-29 09:26:59 +00007388 llvm_unreachable("Implement any new match types added!");
Chris Lattner9487de62010-10-28 21:28:01 +00007389}
7390
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007391/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00007392bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7393 StringRef IDVal = DirectiveID.getIdentifier();
7394 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007395 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007396 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007397 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00007398 else if (IDVal == ".arm")
7399 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007400 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007401 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007402 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007403 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007404 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007405 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00007406 else if (IDVal == ".unreq")
7407 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kim135d2442011-12-20 17:38:12 +00007408 else if (IDVal == ".arch")
7409 return parseDirectiveArch(DirectiveID.getLoc());
7410 else if (IDVal == ".eabi_attribute")
7411 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00007412 return true;
7413}
7414
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007415/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00007416/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007417bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00007418 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7419 for (;;) {
7420 const MCExpr *Value;
7421 if (getParser().ParseExpression(Value))
7422 return true;
7423
Chris Lattnerc35681b2010-01-19 19:46:13 +00007424 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00007425
7426 if (getLexer().is(AsmToken::EndOfStatement))
7427 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00007428
Kevin Enderbyccab3172009-09-15 00:27:25 +00007429 // FIXME: Improve diagnostic.
7430 if (getLexer().isNot(AsmToken::Comma))
7431 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007432 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007433 }
7434 }
7435
Sean Callanana83fd7d2010-01-19 20:27:46 +00007436 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007437 return false;
7438}
7439
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007440/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00007441/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007442bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00007443 if (getLexer().isNot(AsmToken::EndOfStatement))
7444 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007445 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007446
Jim Grosbach7f882392011-12-07 18:04:19 +00007447 if (!isThumb())
7448 SwitchMode();
7449 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7450 return false;
7451}
7452
7453/// parseDirectiveARM
7454/// ::= .arm
7455bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7456 if (getLexer().isNot(AsmToken::EndOfStatement))
7457 return Error(L, "unexpected token in directive");
7458 Parser.Lex();
7459
7460 if (isThumb())
7461 SwitchMode();
7462 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00007463 return false;
7464}
7465
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007466/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00007467/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007468bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007469 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7470 bool isMachO = MAI.hasSubsectionsViaSymbols();
7471 StringRef Name;
Jim Grosbach1152cc02011-12-21 22:30:16 +00007472 bool needFuncName = true;
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007473
Jim Grosbach1152cc02011-12-21 22:30:16 +00007474 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007475 // ELF doesn't
7476 if (isMachO) {
7477 const AsmToken &Tok = Parser.getTok();
Jim Grosbach1152cc02011-12-21 22:30:16 +00007478 if (Tok.isNot(AsmToken::EndOfStatement)) {
7479 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7480 return Error(L, "unexpected token in .thumb_func directive");
7481 Name = Tok.getIdentifier();
7482 Parser.Lex(); // Consume the identifier token.
7483 needFuncName = false;
7484 }
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007485 }
7486
Jim Grosbach1152cc02011-12-21 22:30:16 +00007487 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00007488 return Error(L, "unexpected token in directive");
Jim Grosbach1152cc02011-12-21 22:30:16 +00007489
7490 // Eat the end of statement and any blank lines that follow.
7491 while (getLexer().is(AsmToken::EndOfStatement))
7492 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007493
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007494 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbach1152cc02011-12-21 22:30:16 +00007495 // We really should be checking the next symbol definition even if there's
7496 // stuff in between.
7497 if (needFuncName) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00007498 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007499 }
7500
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00007501 // Mark symbol as a thumb symbol.
7502 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7503 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00007504 return false;
7505}
7506
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007507/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00007508/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007509bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00007510 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007511 if (Tok.isNot(AsmToken::Identifier))
7512 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00007513 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00007514 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00007515 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00007516 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00007517 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00007518 else
7519 return Error(L, "unrecognized syntax mode in .syntax directive");
7520
7521 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00007522 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007523 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007524
7525 // TODO tell the MC streamer the mode
7526 // getParser().getStreamer().Emit???();
7527 return false;
7528}
7529
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007530/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00007531/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007532bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00007533 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007534 if (Tok.isNot(AsmToken::Integer))
7535 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00007536 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00007537 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00007538 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00007539 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00007540 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007541 else
7542 return Error(L, "invalid operand to .code directive");
7543
7544 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00007545 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007546 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007547
Evan Cheng284b4672011-07-08 22:36:29 +00007548 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00007549 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00007550 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00007551 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00007552 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00007553 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00007554 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00007555 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00007556 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00007557
Kevin Enderby146dcf22009-10-15 20:48:48 +00007558 return false;
7559}
7560
Jim Grosbachab5830e2011-12-14 02:16:11 +00007561/// parseDirectiveReq
7562/// ::= name .req registername
7563bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7564 Parser.Lex(); // Eat the '.req' token.
7565 unsigned Reg;
7566 SMLoc SRegLoc, ERegLoc;
7567 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7568 Parser.EatToEndOfStatement();
7569 return Error(SRegLoc, "register name expected");
7570 }
7571
7572 // Shouldn't be anything else.
7573 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7574 Parser.EatToEndOfStatement();
7575 return Error(Parser.getTok().getLoc(),
7576 "unexpected input in .req directive.");
7577 }
7578
7579 Parser.Lex(); // Consume the EndOfStatement
7580
7581 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7582 return Error(SRegLoc, "redefinition of '" + Name +
7583 "' does not match original.");
7584
7585 return false;
7586}
7587
7588/// parseDirectiveUneq
7589/// ::= .unreq registername
7590bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7591 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7592 Parser.EatToEndOfStatement();
7593 return Error(L, "unexpected input in .unreq directive.");
7594 }
7595 RegisterReqs.erase(Parser.getTok().getIdentifier());
7596 Parser.Lex(); // Eat the identifier.
7597 return false;
7598}
7599
Jason W Kim135d2442011-12-20 17:38:12 +00007600/// parseDirectiveArch
7601/// ::= .arch token
7602bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7603 return true;
7604}
7605
7606/// parseDirectiveEabiAttr
7607/// ::= .eabi_attribute int, int
7608bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7609 return true;
7610}
7611
Sean Callanan643a5572010-04-07 20:29:34 +00007612extern "C" void LLVMInitializeARMAsmLexer();
7613
Kevin Enderby8be42bd2009-10-30 22:55:57 +00007614/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00007615extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00007616 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7617 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00007618 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007619}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00007620
Chris Lattner3e4582a2010-09-06 19:11:01 +00007621#define GET_REGISTER_MATCHER
Craig Topper3ec7c2a2012-04-25 06:56:34 +00007622#define GET_SUBTARGET_FEATURE_NAME
Chris Lattner3e4582a2010-09-06 19:11:01 +00007623#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00007624#include "ARMGenAsmMatcher.inc"