blob: 0729da1a8ea20c27768225ac4f035d740aedc3c8 [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
85 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000086 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
87
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000088 int tryParseRegister();
89 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000090 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000091 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000092 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000093 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
94 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000095 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
96 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000097 bool parseDirectiveWord(unsigned Size, SMLoc L);
98 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach7f882392011-12-07 18:04:19 +000099 bool parseDirectiveARM(SMLoc L);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000100 bool parseDirectiveThumbFunc(SMLoc L);
101 bool parseDirectiveCode(SMLoc L);
102 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbachab5830e2011-12-14 02:16:11 +0000103 bool parseDirectiveReq(StringRef Name, SMLoc L);
104 bool parseDirectiveUnreq(SMLoc L);
Jason W Kim135d2442011-12-20 17:38:12 +0000105 bool parseDirectiveArch(SMLoc L);
106 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +0000107
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000108 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000109 bool &CarrySetting, unsigned &ProcessorIMod,
110 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000111 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000112 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000113
Evan Cheng4d1ca962011-07-08 01:53:10 +0000114 bool isThumb() const {
115 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000116 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000117 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000118 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000119 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000120 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000121 bool isThumbTwo() const {
122 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
123 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000124 bool hasV6Ops() const {
125 return STI.getFeatureBits() & ARM::HasV6Ops;
126 }
James Molloy21efa7d2011-09-28 14:21:38 +0000127 bool hasV7Ops() const {
128 return STI.getFeatureBits() & ARM::HasV7Ops;
129 }
Evan Cheng284b4672011-07-08 22:36:29 +0000130 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000131 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
132 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000133 }
James Molloy21efa7d2011-09-28 14:21:38 +0000134 bool isMClass() const {
135 return STI.getFeatureBits() & ARM::FeatureMClass;
136 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000137
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000138 /// @name Auto-generated Match Functions
139 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000140
Chris Lattner3e4582a2010-09-06 19:11:01 +0000141#define GET_ASSEMBLER_HEADER
142#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000143
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000144 /// }
145
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000146 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000147 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000149 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000150 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000151 OperandMatchResultTy parseCoprocOptionOperand(
152 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000153 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000154 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000155 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000156 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000157 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000158 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000159 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
160 StringRef Op, int Low, int High);
161 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
162 return parsePKHImm(O, "lsl", 0, 31);
163 }
164 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
165 return parsePKHImm(O, "asr", 1, 32);
166 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000167 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000168 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000169 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000170 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000171 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000172 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000173 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000174 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach04945c42011-12-02 00:35:16 +0000175 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000176
177 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000178 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
180 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000182 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000184 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000186 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000188 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000190 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000192 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000194 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000196 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
198 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
200 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
202 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000204 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000206 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000208 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000210 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach3ea06572011-10-24 22:16:58 +0000212 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
213 const SmallVectorImpl<MCParsedAsmOperand*> &);
214 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
215 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach05df4602011-10-31 21:50:31 +0000216 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
217 const SmallVectorImpl<MCParsedAsmOperand*> &);
218 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
219 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000220
221 bool validateInstruction(MCInst &Inst,
222 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachafad0532011-11-10 23:42:14 +0000223 bool processInstruction(MCInst &Inst,
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000224 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000225 bool shouldOmitCCOutOperand(StringRef Mnemonic,
226 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000227
Kevin Enderbyccab3172009-09-15 00:27:25 +0000228public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000229 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000230 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000231 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000232 Match_RequiresV6,
233 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000234 };
235
Evan Cheng91111d22011-07-09 05:47:46 +0000236 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000237 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000238 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000239
Jim Grosbachc988e0c2012-03-05 19:33:30 +0000240 // Cache the MCRegisterInfo.
241 MRI = &getContext().getRegisterInfo();
242
Evan Cheng4d1ca962011-07-08 01:53:10 +0000243 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000244 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000245
246 // Not in an ITBlock to start with.
247 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000248 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000249
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000250 // Implementation of the MCTargetAsmParser interface:
251 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
252 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000253 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000254 bool ParseDirective(AsmToken DirectiveID);
255
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000256 unsigned checkTargetMatchPredicate(MCInst &Inst);
257
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000258 bool MatchAndEmitInstruction(SMLoc IDLoc,
259 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
260 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000261};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000262} // end anonymous namespace
263
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000264namespace {
265
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000266/// ARMOperand - Instances of this class represent a parsed ARM machine
267/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000268class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000269 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000270 k_CondCode,
271 k_CCOut,
272 k_ITCondMask,
273 k_CoprocNum,
274 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000275 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000276 k_Immediate,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000277 k_MemBarrierOpt,
278 k_Memory,
279 k_PostIndexRegister,
280 k_MSRMask,
281 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000282 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000283 k_Register,
284 k_RegisterList,
285 k_DPRRegisterList,
286 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000287 k_VectorList,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000288 k_VectorListAllLanes,
Jim Grosbach04945c42011-12-02 00:35:16 +0000289 k_VectorListIndexed,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000290 k_ShiftedRegister,
291 k_ShiftedImmediate,
292 k_ShifterImmediate,
293 k_RotateImmediate,
294 k_BitfieldDescriptor,
295 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000296 } Kind;
297
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000298 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000299 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000300
301 union {
302 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000303 ARMCC::CondCodes Val;
304 } CC;
305
306 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000307 unsigned Val;
308 } Cop;
309
310 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000311 unsigned Val;
312 } CoprocOption;
313
314 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000315 unsigned Mask:4;
316 } ITMask;
317
318 struct {
319 ARM_MB::MemBOpt Val;
320 } MBOpt;
321
322 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000323 ARM_PROC::IFlags Val;
324 } IFlags;
325
326 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000327 unsigned Val;
328 } MMask;
329
330 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000331 const char *Data;
332 unsigned Length;
333 } Tok;
334
335 struct {
336 unsigned RegNum;
337 } Reg;
338
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000339 // A vector register list is a sequential list of 1 to 4 registers.
340 struct {
341 unsigned RegNum;
342 unsigned Count;
Jim Grosbach04945c42011-12-02 00:35:16 +0000343 unsigned LaneIndex;
Jim Grosbach2f50e922011-12-15 21:44:33 +0000344 bool isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000345 } VectorList;
346
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000347 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000348 unsigned Val;
349 } VectorIndex;
350
351 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000352 const MCExpr *Val;
353 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000354
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000355 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000356 struct {
357 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000358 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
359 // was specified.
360 const MCConstantExpr *OffsetImm; // Offset immediate value
361 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
362 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000363 unsigned ShiftImm; // shift for OffsetReg.
364 unsigned Alignment; // 0 = no alignment specified
Jim Grosbachcef98cd2011-12-19 18:31:43 +0000365 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000366 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000367 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000368
369 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000370 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000371 bool isAdd;
372 ARM_AM::ShiftOpc ShiftTy;
373 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000374 } PostIdxReg;
375
376 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000377 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000378 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000379 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000380 struct {
381 ARM_AM::ShiftOpc ShiftTy;
382 unsigned SrcReg;
383 unsigned ShiftReg;
384 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000385 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000386 struct {
387 ARM_AM::ShiftOpc ShiftTy;
388 unsigned SrcReg;
389 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000390 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000391 struct {
392 unsigned Imm;
393 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000394 struct {
395 unsigned LSB;
396 unsigned Width;
397 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000398 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000399
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000400 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
401public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000402 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
403 Kind = o.Kind;
404 StartLoc = o.StartLoc;
405 EndLoc = o.EndLoc;
406 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000407 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000408 CC = o.CC;
409 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000410 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000411 ITMask = o.ITMask;
412 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000413 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000414 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000415 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000416 case k_CCOut:
417 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000418 Reg = o.Reg;
419 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000420 case k_RegisterList:
421 case k_DPRRegisterList:
422 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000423 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000424 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000425 case k_VectorList:
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000426 case k_VectorListAllLanes:
Jim Grosbach04945c42011-12-02 00:35:16 +0000427 case k_VectorListIndexed:
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000428 VectorList = o.VectorList;
429 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000430 case k_CoprocNum:
431 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000432 Cop = o.Cop;
433 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000434 case k_CoprocOption:
435 CoprocOption = o.CoprocOption;
436 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000437 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000438 Imm = o.Imm;
439 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000440 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000441 MBOpt = o.MBOpt;
442 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000443 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000444 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000445 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000446 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000447 PostIdxReg = o.PostIdxReg;
448 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000449 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000450 MMask = o.MMask;
451 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000452 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000453 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000454 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000455 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000456 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000457 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000458 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000459 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000460 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000461 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000462 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000463 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000464 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000465 RotImm = o.RotImm;
466 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000467 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000468 Bitfield = o.Bitfield;
469 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000470 case k_VectorIndex:
471 VectorIndex = o.VectorIndex;
472 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000473 }
474 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000475
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000476 /// getStartLoc - Get the location of the first token of this operand.
477 SMLoc getStartLoc() const { return StartLoc; }
478 /// getEndLoc - Get the location of the last token of this operand.
479 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000480
Daniel Dunbard8042b72010-08-11 06:36:53 +0000481 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000482 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000483 return CC.Val;
484 }
485
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000486 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000487 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000488 return Cop.Val;
489 }
490
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000491 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000492 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000493 return StringRef(Tok.Data, Tok.Length);
494 }
495
496 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000497 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000498 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000499 }
500
Bill Wendlingbed94652010-11-09 23:28:44 +0000501 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000502 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
503 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000504 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000505 }
506
Kevin Enderbyf5079942009-10-13 22:19:02 +0000507 const MCExpr *getImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000508 assert(isImm() && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000509 return Imm.Val;
510 }
511
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000512 unsigned getVectorIndex() const {
513 assert(Kind == k_VectorIndex && "Invalid access!");
514 return VectorIndex.Val;
515 }
516
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000517 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000518 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000519 return MBOpt.Val;
520 }
521
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000522 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000523 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000524 return IFlags.Val;
525 }
526
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000527 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000528 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000529 return MMask.Val;
530 }
531
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000532 bool isCoprocNum() const { return Kind == k_CoprocNum; }
533 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000534 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000535 bool isCondCode() const { return Kind == k_CondCode; }
536 bool isCCOut() const { return Kind == k_CCOut; }
537 bool isITMask() const { return Kind == k_ITCondMask; }
538 bool isITCondCode() const { return Kind == k_CondCode; }
539 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +0000540 bool isFPImm() const {
541 if (!isImm()) return false;
542 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
543 if (!CE) return false;
544 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
545 return Val != -1;
546 }
Jim Grosbachea231912011-12-22 22:19:05 +0000547 bool isFBits16() const {
548 if (!isImm()) return false;
549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
550 if (!CE) return false;
551 int64_t Value = CE->getValue();
552 return Value >= 0 && Value <= 16;
553 }
554 bool isFBits32() const {
555 if (!isImm()) return false;
556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
557 if (!CE) return false;
558 int64_t Value = CE->getValue();
559 return Value >= 1 && Value <= 32;
560 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000561 bool isImm8s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000562 if (!isImm()) return false;
Jim Grosbach7db8d692011-09-08 22:07:06 +0000563 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
564 if (!CE) return false;
565 int64_t Value = CE->getValue();
566 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
567 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000568 bool isImm0_1020s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000569 if (!isImm()) return false;
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000570 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
571 if (!CE) return false;
572 int64_t Value = CE->getValue();
573 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
574 }
575 bool isImm0_508s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000576 if (!isImm()) return false;
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
581 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000582 bool isImm0_255() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000583 if (!isImm()) return false;
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
585 if (!CE) return false;
586 int64_t Value = CE->getValue();
587 return Value >= 0 && Value < 256;
588 }
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000589 bool isImm0_1() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000590 if (!isImm()) return false;
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000591 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
592 if (!CE) return false;
593 int64_t Value = CE->getValue();
594 return Value >= 0 && Value < 2;
595 }
596 bool isImm0_3() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000597 if (!isImm()) return false;
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
599 if (!CE) return false;
600 int64_t Value = CE->getValue();
601 return Value >= 0 && Value < 4;
602 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000603 bool isImm0_7() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000604 if (!isImm()) return false;
Jim Grosbach31756c22011-07-13 22:01:08 +0000605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
606 if (!CE) return false;
607 int64_t Value = CE->getValue();
608 return Value >= 0 && Value < 8;
609 }
610 bool isImm0_15() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000611 if (!isImm()) return false;
Jim Grosbach31756c22011-07-13 22:01:08 +0000612 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
613 if (!CE) return false;
614 int64_t Value = CE->getValue();
615 return Value >= 0 && Value < 16;
616 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000617 bool isImm0_31() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000618 if (!isImm()) return false;
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000619 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
620 if (!CE) return false;
621 int64_t Value = CE->getValue();
622 return Value >= 0 && Value < 32;
623 }
Jim Grosbach00326402011-12-08 01:30:04 +0000624 bool isImm0_63() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000625 if (!isImm()) return false;
Jim Grosbach00326402011-12-08 01:30:04 +0000626 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
627 if (!CE) return false;
628 int64_t Value = CE->getValue();
629 return Value >= 0 && Value < 64;
630 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000631 bool isImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000632 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 8;
637 }
638 bool isImm16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000639 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000640 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
641 if (!CE) return false;
642 int64_t Value = CE->getValue();
643 return Value == 16;
644 }
645 bool isImm32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000646 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
648 if (!CE) return false;
649 int64_t Value = CE->getValue();
650 return Value == 32;
651 }
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000652 bool isShrImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000653 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000654 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
655 if (!CE) return false;
656 int64_t Value = CE->getValue();
657 return Value > 0 && Value <= 8;
658 }
659 bool isShrImm16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000660 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000661 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
662 if (!CE) return false;
663 int64_t Value = CE->getValue();
664 return Value > 0 && Value <= 16;
665 }
666 bool isShrImm32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000667 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000668 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
669 if (!CE) return false;
670 int64_t Value = CE->getValue();
671 return Value > 0 && Value <= 32;
672 }
673 bool isShrImm64() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000674 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000675 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
676 if (!CE) return false;
677 int64_t Value = CE->getValue();
678 return Value > 0 && Value <= 64;
679 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000680 bool isImm1_7() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000681 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000682 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
683 if (!CE) return false;
684 int64_t Value = CE->getValue();
685 return Value > 0 && Value < 8;
686 }
687 bool isImm1_15() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000688 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value > 0 && Value < 16;
693 }
694 bool isImm1_31() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000695 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000696 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
697 if (!CE) return false;
698 int64_t Value = CE->getValue();
699 return Value > 0 && Value < 32;
700 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000701 bool isImm1_16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000702 if (!isImm()) return false;
Jim Grosbach475c6db2011-07-25 23:09:14 +0000703 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
704 if (!CE) return false;
705 int64_t Value = CE->getValue();
706 return Value > 0 && Value < 17;
707 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000708 bool isImm1_32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000709 if (!isImm()) return false;
Jim Grosbach801e0a32011-07-22 23:16:18 +0000710 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
711 if (!CE) return false;
712 int64_t Value = CE->getValue();
713 return Value > 0 && Value < 33;
714 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000715 bool isImm0_32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000716 if (!isImm()) return false;
Jim Grosbachc14871c2011-11-10 19:18:01 +0000717 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
718 if (!CE) return false;
719 int64_t Value = CE->getValue();
720 return Value >= 0 && Value < 33;
721 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000722 bool isImm0_65535() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000723 if (!isImm()) return false;
Jim Grosbach975b6412011-07-13 20:10:10 +0000724 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
725 if (!CE) return false;
726 int64_t Value = CE->getValue();
727 return Value >= 0 && Value < 65536;
728 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000729 bool isImm0_65535Expr() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000730 if (!isImm()) return false;
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000731 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
732 // If it's not a constant expression, it'll generate a fixup and be
733 // handled later.
734 if (!CE) return true;
735 int64_t Value = CE->getValue();
736 return Value >= 0 && Value < 65536;
737 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000738 bool isImm24bit() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000739 if (!isImm()) return false;
Jim Grosbachf1637842011-07-26 16:24:27 +0000740 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
741 if (!CE) return false;
742 int64_t Value = CE->getValue();
743 return Value >= 0 && Value <= 0xffffff;
744 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000745 bool isImmThumbSR() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000746 if (!isImm()) return false;
Jim Grosbach46dd4132011-08-17 21:51:27 +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 Grosbach27c1e252011-07-21 17:23:04 +0000752 bool isPKHLSLImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000753 if (!isImm()) return false;
Jim Grosbach27c1e252011-07-21 17:23:04 +0000754 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
755 if (!CE) return false;
756 int64_t Value = CE->getValue();
757 return Value >= 0 && Value < 32;
758 }
759 bool isPKHASRImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000760 if (!isImm()) return false;
Jim Grosbach27c1e252011-07-21 17:23:04 +0000761 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
762 if (!CE) return false;
763 int64_t Value = CE->getValue();
764 return Value > 0 && Value <= 32;
765 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000766 bool isARMSOImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000767 if (!isImm()) return false;
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000768 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
769 if (!CE) return false;
770 int64_t Value = CE->getValue();
771 return ARM_AM::getSOImmVal(Value) != -1;
772 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000773 bool isARMSOImmNot() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000774 if (!isImm()) return false;
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000775 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
776 if (!CE) return false;
777 int64_t Value = CE->getValue();
778 return ARM_AM::getSOImmVal(~Value) != -1;
779 }
Jim Grosbach30506252011-12-08 00:31:07 +0000780 bool isARMSOImmNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000781 if (!isImm()) return false;
Jim Grosbach30506252011-12-08 00:31:07 +0000782 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
783 if (!CE) return false;
784 int64_t Value = CE->getValue();
Jim Grosbachfdaab532012-03-30 19:59:02 +0000785 // Only use this when not representable as a plain so_imm.
786 return ARM_AM::getSOImmVal(Value) == -1 &&
787 ARM_AM::getSOImmVal(-Value) != -1;
Jim Grosbach30506252011-12-08 00:31:07 +0000788 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000789 bool isT2SOImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000790 if (!isImm()) return false;
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000791 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
792 if (!CE) return false;
793 int64_t Value = CE->getValue();
794 return ARM_AM::getT2SOImmVal(Value) != -1;
795 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000796 bool isT2SOImmNot() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000797 if (!isImm()) return false;
Jim Grosbachb009a872011-10-28 22:36:30 +0000798 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
799 if (!CE) return false;
800 int64_t Value = CE->getValue();
801 return ARM_AM::getT2SOImmVal(~Value) != -1;
802 }
Jim Grosbach30506252011-12-08 00:31:07 +0000803 bool isT2SOImmNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000804 if (!isImm()) return false;
Jim Grosbach30506252011-12-08 00:31:07 +0000805 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
806 if (!CE) return false;
807 int64_t Value = CE->getValue();
Jim Grosbachfdaab532012-03-30 19:59:02 +0000808 // Only use this when not representable as a plain so_imm.
809 return ARM_AM::getT2SOImmVal(Value) == -1 &&
810 ARM_AM::getT2SOImmVal(-Value) != -1;
Jim Grosbach30506252011-12-08 00:31:07 +0000811 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000812 bool isSetEndImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000813 if (!isImm()) return false;
Jim Grosbach0a547702011-07-22 17:44:50 +0000814 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
815 if (!CE) return false;
816 int64_t Value = CE->getValue();
817 return Value == 1 || Value == 0;
818 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000819 bool isReg() const { return Kind == k_Register; }
820 bool isRegList() const { return Kind == k_RegisterList; }
821 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
822 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
823 bool isToken() const { return Kind == k_Token; }
824 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
825 bool isMemory() const { return Kind == k_Memory; }
826 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
827 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
828 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
829 bool isRotImm() const { return Kind == k_RotateImmediate; }
830 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
831 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000832 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000833 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000834 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000835 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000836 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000837 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000838 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000839 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
840 (alignOK || Memory.Alignment == 0);
841 }
Jim Grosbach94298a92012-01-18 22:46:46 +0000842 bool isMemPCRelImm12() const {
843 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
844 return false;
845 // Base register must be PC.
846 if (Memory.BaseRegNum != ARM::PC)
847 return false;
848 // Immediate offset in range [-4095, 4095].
849 if (!Memory.OffsetImm) return true;
850 int64_t Val = Memory.OffsetImm->getValue();
851 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
852 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000853 bool isAlignedMemory() const {
854 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000855 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000856 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000857 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000858 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000859 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000860 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000861 if (!Memory.OffsetImm) return true;
862 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000863 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000864 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000865 bool isAM2OffsetImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000866 if (!isImm()) return false;
Jim Grosbachcd17c122011-08-04 23:01:30 +0000867 // Immediate offset in range [-4095, 4095].
868 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
869 if (!CE) return false;
870 int64_t Val = CE->getValue();
871 return Val > -4096 && Val < 4096;
872 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000873 bool isAddrMode3() const {
Jim Grosbach8648c102011-12-19 23:06:24 +0000874 // If we have an immediate that's not a constant, treat it as a label
875 // reference needing a fixup. If it is a constant, it's something else
876 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000877 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +0000878 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000879 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000880 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000881 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000882 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000883 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000884 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000885 if (!Memory.OffsetImm) return true;
886 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000887 return Val > -256 && Val < 256;
888 }
889 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000890 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000891 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000892 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000893 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
894 // Immediate offset in range [-255, 255].
895 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
896 if (!CE) return false;
897 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000898 // Special case, #-0 is INT32_MIN.
899 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000900 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000901 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000902 // If we have an immediate that's not a constant, treat it as a label
903 // reference needing a fixup. If it is a constant, it's something else
904 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000905 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000906 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000907 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000908 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000909 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000910 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000911 if (!Memory.OffsetImm) return true;
912 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000913 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000914 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000915 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000916 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000917 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000918 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000919 return false;
920 return true;
921 }
922 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000923 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000924 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
925 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000926 return false;
927 return true;
928 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000929 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000930 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000931 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000932 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000933 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000934 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000935 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
936 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000937 return false;
938 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000939 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000940 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000941 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000942 return false;
943 return true;
944 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000945 bool isMemThumbRR() const {
946 // Thumb reg+reg addressing is simple. Just two registers, a base and
947 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000948 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000949 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000950 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000951 return isARMLowRegister(Memory.BaseRegNum) &&
952 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000953 }
954 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000955 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000956 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000957 return false;
958 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000959 if (!Memory.OffsetImm) return true;
960 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000961 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
962 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000963 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000964 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000965 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000966 return false;
967 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000968 if (!Memory.OffsetImm) return true;
969 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000970 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
971 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000972 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000973 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000974 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000975 return false;
976 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000977 if (!Memory.OffsetImm) return true;
978 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000979 return Val >= 0 && Val <= 31;
980 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000981 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000982 if (!isMemory() || Memory.OffsetRegNum != 0 ||
983 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000984 return false;
985 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000986 if (!Memory.OffsetImm) return true;
987 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000988 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000989 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000990 bool isMemImm8s4Offset() const {
Jim Grosbach8648c102011-12-19 23:06:24 +0000991 // If we have an immediate that's not a constant, treat it as a label
992 // reference needing a fixup. If it is a constant, it's something else
993 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000994 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +0000995 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000996 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000997 return false;
998 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000999 if (!Memory.OffsetImm) return true;
1000 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +00001001 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1002 }
Jim Grosbacha05627e2011-09-09 18:37:27 +00001003 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001004 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +00001005 return false;
1006 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001007 if (!Memory.OffsetImm) return true;
1008 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001009 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1010 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001011 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001012 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001013 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001014 // Base reg of PC isn't allowed for these encodings.
1015 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001016 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001017 if (!Memory.OffsetImm) return true;
1018 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001019 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001020 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001021 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001022 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001023 return false;
1024 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001025 if (!Memory.OffsetImm) return true;
1026 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001027 return Val >= 0 && Val < 256;
1028 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001029 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001030 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001031 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001032 // Base reg of PC isn't allowed for these encodings.
1033 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001034 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001035 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001036 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001037 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001038 }
1039 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001040 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001041 return false;
1042 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001043 if (!Memory.OffsetImm) return true;
1044 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001045 return (Val >= 0 && Val < 4096);
1046 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001047 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001048 // If we have an immediate that's not a constant, treat it as a label
1049 // reference needing a fixup. If it is a constant, it's something else
1050 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001051 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001052 return true;
1053
Jim Grosbacha95ec992011-10-11 17:29:55 +00001054 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001055 return false;
1056 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001057 if (!Memory.OffsetImm) return true;
1058 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001059 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001060 }
1061 bool isPostIdxImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001062 if (!isImm()) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001063 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1064 if (!CE) return false;
1065 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001066 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001067 }
Jim Grosbach93981412011-10-11 21:55:36 +00001068 bool isPostIdxImm8s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001069 if (!isImm()) return false;
Jim Grosbach93981412011-10-11 21:55:36 +00001070 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1071 if (!CE) return false;
1072 int64_t Val = CE->getValue();
1073 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1074 (Val == INT32_MIN);
1075 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001076
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001077 bool isMSRMask() const { return Kind == k_MSRMask; }
1078 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001079
Jim Grosbach741cd732011-10-17 22:26:03 +00001080 // NEON operands.
Jim Grosbach2f50e922011-12-15 21:44:33 +00001081 bool isSingleSpacedVectorList() const {
1082 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1083 }
1084 bool isDoubleSpacedVectorList() const {
1085 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1086 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001087 bool isVecListOneD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001088 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001089 return VectorList.Count == 1;
1090 }
1091
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001092 bool isVecListDPair() const {
1093 if (!isSingleSpacedVectorList()) return false;
1094 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1095 .contains(VectorList.RegNum));
1096 }
1097
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001098 bool isVecListThreeD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001099 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001100 return VectorList.Count == 3;
1101 }
1102
Jim Grosbach846bcff2011-10-21 20:35:01 +00001103 bool isVecListFourD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001104 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach846bcff2011-10-21 20:35:01 +00001105 return VectorList.Count == 4;
1106 }
1107
Jim Grosbache5307f92012-03-05 21:43:40 +00001108 bool isVecListDPairSpaced() const {
Kevin Enderby816ca272012-03-20 17:41:51 +00001109 if (isSingleSpacedVectorList()) return false;
Jim Grosbache5307f92012-03-05 21:43:40 +00001110 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1111 .contains(VectorList.RegNum));
1112 }
1113
Jim Grosbachac2af3f2012-01-23 23:20:46 +00001114 bool isVecListThreeQ() const {
1115 if (!isDoubleSpacedVectorList()) return false;
1116 return VectorList.Count == 3;
1117 }
1118
Jim Grosbach1e946a42012-01-24 00:43:12 +00001119 bool isVecListFourQ() const {
1120 if (!isDoubleSpacedVectorList()) return false;
1121 return VectorList.Count == 4;
1122 }
1123
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001124 bool isSingleSpacedVectorAllLanes() const {
1125 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1126 }
1127 bool isDoubleSpacedVectorAllLanes() const {
1128 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1129 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001130 bool isVecListOneDAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001131 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001132 return VectorList.Count == 1;
1133 }
1134
Jim Grosbach13a292c2012-03-06 22:01:44 +00001135 bool isVecListDPairAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001136 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach13a292c2012-03-06 22:01:44 +00001137 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1138 .contains(VectorList.RegNum));
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001139 }
1140
Jim Grosbached428bc2012-03-06 23:10:38 +00001141 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001142 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001143 return VectorList.Count == 2;
1144 }
1145
Jim Grosbachb78403c2012-01-24 23:47:04 +00001146 bool isVecListThreeDAllLanes() const {
1147 if (!isSingleSpacedVectorAllLanes()) return false;
1148 return VectorList.Count == 3;
1149 }
1150
1151 bool isVecListThreeQAllLanes() const {
1152 if (!isDoubleSpacedVectorAllLanes()) return false;
1153 return VectorList.Count == 3;
1154 }
1155
Jim Grosbach086cbfa2012-01-25 00:01:08 +00001156 bool isVecListFourDAllLanes() const {
1157 if (!isSingleSpacedVectorAllLanes()) return false;
1158 return VectorList.Count == 4;
1159 }
1160
1161 bool isVecListFourQAllLanes() const {
1162 if (!isDoubleSpacedVectorAllLanes()) return false;
1163 return VectorList.Count == 4;
1164 }
1165
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001166 bool isSingleSpacedVectorIndexed() const {
1167 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1168 }
1169 bool isDoubleSpacedVectorIndexed() const {
1170 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1171 }
Jim Grosbach04945c42011-12-02 00:35:16 +00001172 bool isVecListOneDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001173 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach04945c42011-12-02 00:35:16 +00001174 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1175 }
1176
Jim Grosbachda511042011-12-14 23:35:06 +00001177 bool isVecListOneDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001178 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001179 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1180 }
1181
1182 bool isVecListOneDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001183 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001184 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1185 }
1186
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001187 bool isVecListTwoDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001188 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001189 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1190 }
1191
Jim Grosbachda511042011-12-14 23:35:06 +00001192 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001193 if (!isSingleSpacedVectorIndexed()) return false;
1194 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1195 }
1196
1197 bool isVecListTwoQWordIndexed() const {
1198 if (!isDoubleSpacedVectorIndexed()) return false;
1199 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1200 }
1201
1202 bool isVecListTwoQHWordIndexed() const {
1203 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001204 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1205 }
1206
1207 bool isVecListTwoDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001208 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001209 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1210 }
1211
Jim Grosbacha8b444b2012-01-23 21:53:26 +00001212 bool isVecListThreeDByteIndexed() const {
1213 if (!isSingleSpacedVectorIndexed()) return false;
1214 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1215 }
1216
1217 bool isVecListThreeDHWordIndexed() const {
1218 if (!isSingleSpacedVectorIndexed()) return false;
1219 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1220 }
1221
1222 bool isVecListThreeQWordIndexed() const {
1223 if (!isDoubleSpacedVectorIndexed()) return false;
1224 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1225 }
1226
1227 bool isVecListThreeQHWordIndexed() const {
1228 if (!isDoubleSpacedVectorIndexed()) return false;
1229 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1230 }
1231
1232 bool isVecListThreeDWordIndexed() const {
1233 if (!isSingleSpacedVectorIndexed()) return false;
1234 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1235 }
1236
Jim Grosbach14952a02012-01-24 18:37:25 +00001237 bool isVecListFourDByteIndexed() const {
1238 if (!isSingleSpacedVectorIndexed()) return false;
1239 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1240 }
1241
1242 bool isVecListFourDHWordIndexed() const {
1243 if (!isSingleSpacedVectorIndexed()) return false;
1244 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1245 }
1246
1247 bool isVecListFourQWordIndexed() const {
1248 if (!isDoubleSpacedVectorIndexed()) return false;
1249 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1250 }
1251
1252 bool isVecListFourQHWordIndexed() const {
1253 if (!isDoubleSpacedVectorIndexed()) return false;
1254 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1255 }
1256
1257 bool isVecListFourDWordIndexed() const {
1258 if (!isSingleSpacedVectorIndexed()) return false;
1259 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1260 }
1261
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001262 bool isVectorIndex8() const {
1263 if (Kind != k_VectorIndex) return false;
1264 return VectorIndex.Val < 8;
1265 }
1266 bool isVectorIndex16() const {
1267 if (Kind != k_VectorIndex) return false;
1268 return VectorIndex.Val < 4;
1269 }
1270 bool isVectorIndex32() const {
1271 if (Kind != k_VectorIndex) return false;
1272 return VectorIndex.Val < 2;
1273 }
1274
Jim Grosbach741cd732011-10-17 22:26:03 +00001275 bool isNEONi8splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001276 if (!isImm()) return false;
Jim Grosbach741cd732011-10-17 22:26:03 +00001277 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1278 // Must be a constant.
1279 if (!CE) return false;
1280 int64_t Value = CE->getValue();
1281 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1282 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001283 return Value >= 0 && Value < 256;
1284 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001285
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001286 bool isNEONi16splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001287 if (!isImm()) return false;
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001288 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1289 // Must be a constant.
1290 if (!CE) return false;
1291 int64_t Value = CE->getValue();
1292 // i16 value in the range [0,255] or [0x0100, 0xff00]
1293 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1294 }
1295
Jim Grosbach8211c052011-10-18 00:22:00 +00001296 bool isNEONi32splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001297 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001298 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1299 // Must be a constant.
1300 if (!CE) return false;
1301 int64_t Value = CE->getValue();
1302 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1303 return (Value >= 0 && Value < 256) ||
1304 (Value >= 0x0100 && Value <= 0xff00) ||
1305 (Value >= 0x010000 && Value <= 0xff0000) ||
1306 (Value >= 0x01000000 && Value <= 0xff000000);
1307 }
1308
1309 bool isNEONi32vmov() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001310 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001311 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1312 // Must be a constant.
1313 if (!CE) return false;
1314 int64_t Value = CE->getValue();
1315 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1316 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1317 return (Value >= 0 && Value < 256) ||
1318 (Value >= 0x0100 && Value <= 0xff00) ||
1319 (Value >= 0x010000 && Value <= 0xff0000) ||
1320 (Value >= 0x01000000 && Value <= 0xff000000) ||
1321 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1322 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1323 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00001324 bool isNEONi32vmovNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001325 if (!isImm()) return false;
Jim Grosbach045b6c72011-12-19 23:51:07 +00001326 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1327 // Must be a constant.
1328 if (!CE) return false;
1329 int64_t Value = ~CE->getValue();
1330 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1331 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1332 return (Value >= 0 && Value < 256) ||
1333 (Value >= 0x0100 && Value <= 0xff00) ||
1334 (Value >= 0x010000 && Value <= 0xff0000) ||
1335 (Value >= 0x01000000 && Value <= 0xff000000) ||
1336 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1337 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1338 }
Jim Grosbach8211c052011-10-18 00:22:00 +00001339
Jim Grosbache4454e02011-10-18 16:18:11 +00001340 bool isNEONi64splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001341 if (!isImm()) return false;
Jim Grosbache4454e02011-10-18 16:18:11 +00001342 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1343 // Must be a constant.
1344 if (!CE) return false;
1345 uint64_t Value = CE->getValue();
1346 // i64 value with each byte being either 0 or 0xff.
1347 for (unsigned i = 0; i < 8; ++i)
1348 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1349 return true;
1350 }
1351
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001352 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001353 // Add as immediates when possible. Null MCExpr = 0.
1354 if (Expr == 0)
1355 Inst.addOperand(MCOperand::CreateImm(0));
1356 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001357 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1358 else
1359 Inst.addOperand(MCOperand::CreateExpr(Expr));
1360 }
1361
Daniel Dunbard8042b72010-08-11 06:36:53 +00001362 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001363 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001364 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001365 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1366 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001367 }
1368
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001369 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1370 assert(N == 1 && "Invalid number of operands!");
1371 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1372 }
1373
Jim Grosbach48399582011-10-12 17:34:41 +00001374 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1375 assert(N == 1 && "Invalid number of operands!");
1376 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1377 }
1378
1379 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1380 assert(N == 1 && "Invalid number of operands!");
1381 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1382 }
1383
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001384 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1385 assert(N == 1 && "Invalid number of operands!");
1386 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1387 }
1388
1389 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1390 assert(N == 1 && "Invalid number of operands!");
1391 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1392 }
1393
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001394 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1395 assert(N == 1 && "Invalid number of operands!");
1396 Inst.addOperand(MCOperand::CreateReg(getReg()));
1397 }
1398
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001399 void addRegOperands(MCInst &Inst, unsigned N) const {
1400 assert(N == 1 && "Invalid number of operands!");
1401 Inst.addOperand(MCOperand::CreateReg(getReg()));
1402 }
1403
Jim Grosbachac798e12011-07-25 20:49:51 +00001404 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001405 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001406 assert(isRegShiftedReg() &&
1407 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001408 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1409 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001410 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001411 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001412 }
1413
Jim Grosbachac798e12011-07-25 20:49:51 +00001414 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001415 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001416 assert(isRegShiftedImm() &&
1417 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001418 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001419 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001420 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001421 }
1422
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001423 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001424 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001425 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1426 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001427 }
1428
Bill Wendling8d2aa032010-11-08 23:49:57 +00001429 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001430 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001431 const SmallVectorImpl<unsigned> &RegList = getRegList();
1432 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001433 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1434 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001435 }
1436
Bill Wendling9898ac92010-11-17 04:32:08 +00001437 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1438 addRegListOperands(Inst, N);
1439 }
1440
1441 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1442 addRegListOperands(Inst, N);
1443 }
1444
Jim Grosbach833b9d32011-07-27 20:15:40 +00001445 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 1 && "Invalid number of operands!");
1447 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1448 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1449 }
1450
Jim Grosbach864b6092011-07-28 21:34:26 +00001451 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 // Munge the lsb/width into a bitfield mask.
1454 unsigned lsb = Bitfield.LSB;
1455 unsigned width = Bitfield.Width;
1456 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1457 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1458 (32 - (lsb + width)));
1459 Inst.addOperand(MCOperand::CreateImm(Mask));
1460 }
1461
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001462 void addImmOperands(MCInst &Inst, unsigned N) const {
1463 assert(N == 1 && "Invalid number of operands!");
1464 addExpr(Inst, getImm());
1465 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001466
Jim Grosbachea231912011-12-22 22:19:05 +00001467 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
1469 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1470 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1471 }
1472
1473 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
1475 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1476 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1477 }
1478
Jim Grosbache7fbce72011-10-03 23:38:36 +00001479 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00001481 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1482 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1483 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbache7fbce72011-10-03 23:38:36 +00001484 }
1485
Jim Grosbach7db8d692011-09-08 22:07:06 +00001486 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 // FIXME: We really want to scale the value here, but the LDRD/STRD
1489 // instruction don't encode operands that way yet.
1490 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1491 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1492 }
1493
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001494 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 // The immediate is scaled by four in the encoding and is stored
1497 // in the MCInst as such. Lop off the low two bits here.
1498 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1499 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1500 }
1501
1502 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1503 assert(N == 1 && "Invalid number of operands!");
1504 // The immediate is scaled by four in the encoding and is stored
1505 // in the MCInst as such. Lop off the low two bits here.
1506 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1507 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1508 }
1509
Jim Grosbach475c6db2011-07-25 23:09:14 +00001510 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1511 assert(N == 1 && "Invalid number of operands!");
1512 // The constant encodes as the immediate-1, and we store in the instruction
1513 // the bits as encoded, so subtract off one here.
1514 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1515 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1516 }
1517
Jim Grosbach801e0a32011-07-22 23:16:18 +00001518 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1519 assert(N == 1 && "Invalid number of operands!");
1520 // The constant encodes as the immediate-1, and we store in the instruction
1521 // the bits as encoded, so subtract off one here.
1522 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1523 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1524 }
1525
Jim Grosbach46dd4132011-08-17 21:51:27 +00001526 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1527 assert(N == 1 && "Invalid number of operands!");
1528 // The constant encodes as the immediate, except for 32, which encodes as
1529 // zero.
1530 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1531 unsigned Imm = CE->getValue();
1532 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1533 }
1534
Jim Grosbach27c1e252011-07-21 17:23:04 +00001535 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1538 // the instruction as well.
1539 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1540 int Val = CE->getValue();
1541 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1542 }
1543
Jim Grosbachb009a872011-10-28 22:36:30 +00001544 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1545 assert(N == 1 && "Invalid number of operands!");
1546 // The operand is actually a t2_so_imm, but we have its bitwise
1547 // negation in the assembly source, so twiddle it here.
1548 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1549 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1550 }
1551
Jim Grosbach30506252011-12-08 00:31:07 +00001552 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554 // The operand is actually a t2_so_imm, but we have its
1555 // negation in the assembly source, so twiddle it here.
1556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1557 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1558 }
1559
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001560 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 // The operand is actually a so_imm, but we have its bitwise
1563 // negation in the assembly source, so twiddle it here.
1564 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1565 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1566 }
1567
Jim Grosbach30506252011-12-08 00:31:07 +00001568 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
1570 // The operand is actually a so_imm, but we have its
1571 // negation in the assembly source, so twiddle it here.
1572 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1573 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1574 }
1575
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001576 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1577 assert(N == 1 && "Invalid number of operands!");
1578 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1579 }
1580
Jim Grosbachd3595712011-08-03 23:50:40 +00001581 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1582 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001583 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001584 }
1585
Jim Grosbach94298a92012-01-18 22:46:46 +00001586 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1587 assert(N == 1 && "Invalid number of operands!");
1588 int32_t Imm = Memory.OffsetImm->getValue();
1589 // FIXME: Handle #-0
1590 if (Imm == INT32_MIN) Imm = 0;
1591 Inst.addOperand(MCOperand::CreateImm(Imm));
1592 }
1593
Jim Grosbacha95ec992011-10-11 17:29:55 +00001594 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1595 assert(N == 2 && "Invalid number of operands!");
1596 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1597 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1598 }
1599
Jim Grosbachd3595712011-08-03 23:50:40 +00001600 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1601 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001602 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1603 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001604 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1605 // Special case for #-0
1606 if (Val == INT32_MIN) Val = 0;
1607 if (Val < 0) Val = -Val;
1608 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1609 } else {
1610 // For register offset, we encode the shift type and negation flag
1611 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001612 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1613 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001614 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001615 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1616 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001617 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001618 }
1619
Jim Grosbachcd17c122011-08-04 23:01:30 +00001620 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1621 assert(N == 2 && "Invalid number of operands!");
1622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1623 assert(CE && "non-constant AM2OffsetImm operand!");
1624 int32_t Val = CE->getValue();
1625 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1626 // Special case for #-0
1627 if (Val == INT32_MIN) Val = 0;
1628 if (Val < 0) Val = -Val;
1629 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1630 Inst.addOperand(MCOperand::CreateReg(0));
1631 Inst.addOperand(MCOperand::CreateImm(Val));
1632 }
1633
Jim Grosbach5b96b802011-08-10 20:29:19 +00001634 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1635 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001636 // If we have an immediate that's not a constant, treat it as a label
1637 // reference needing a fixup. If it is a constant, it's something else
1638 // and we reject it.
1639 if (isImm()) {
1640 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1641 Inst.addOperand(MCOperand::CreateReg(0));
1642 Inst.addOperand(MCOperand::CreateImm(0));
1643 return;
1644 }
1645
Jim Grosbach871dff72011-10-11 15:59:20 +00001646 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1647 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001648 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1649 // Special case for #-0
1650 if (Val == INT32_MIN) Val = 0;
1651 if (Val < 0) Val = -Val;
1652 Val = ARM_AM::getAM3Opc(AddSub, Val);
1653 } else {
1654 // For register offset, we encode the shift type and negation flag
1655 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001656 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001657 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001658 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1659 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001660 Inst.addOperand(MCOperand::CreateImm(Val));
1661 }
1662
1663 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1664 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001665 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001666 int32_t Val =
1667 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1668 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1669 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001670 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001671 }
1672
1673 // Constant offset.
1674 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1675 int32_t Val = CE->getValue();
1676 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1677 // Special case for #-0
1678 if (Val == INT32_MIN) Val = 0;
1679 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001680 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001681 Inst.addOperand(MCOperand::CreateReg(0));
1682 Inst.addOperand(MCOperand::CreateImm(Val));
1683 }
1684
Jim Grosbachd3595712011-08-03 23:50:40 +00001685 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1686 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001687 // If we have an immediate that's not a constant, treat it as a label
1688 // reference needing a fixup. If it is a constant, it's something else
1689 // and we reject it.
1690 if (isImm()) {
1691 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1692 Inst.addOperand(MCOperand::CreateImm(0));
1693 return;
1694 }
1695
Jim Grosbachd3595712011-08-03 23:50:40 +00001696 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001697 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001698 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1699 // Special case for #-0
1700 if (Val == INT32_MIN) Val = 0;
1701 if (Val < 0) Val = -Val;
1702 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001703 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001704 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001705 }
1706
Jim Grosbach7db8d692011-09-08 22:07:06 +00001707 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1708 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001709 // If we have an immediate that's not a constant, treat it as a label
1710 // reference needing a fixup. If it is a constant, it's something else
1711 // and we reject it.
1712 if (isImm()) {
1713 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1714 Inst.addOperand(MCOperand::CreateImm(0));
1715 return;
1716 }
1717
Jim Grosbach871dff72011-10-11 15:59:20 +00001718 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1719 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001720 Inst.addOperand(MCOperand::CreateImm(Val));
1721 }
1722
Jim Grosbacha05627e2011-09-09 18:37:27 +00001723 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1724 assert(N == 2 && "Invalid number of operands!");
1725 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001726 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1727 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001728 Inst.addOperand(MCOperand::CreateImm(Val));
1729 }
1730
Jim Grosbachd3595712011-08-03 23:50:40 +00001731 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1732 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001733 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1734 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001735 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001736 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001737
Jim Grosbach2392c532011-09-07 23:39:14 +00001738 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1739 addMemImm8OffsetOperands(Inst, N);
1740 }
1741
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001742 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001743 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001744 }
1745
1746 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1747 assert(N == 2 && "Invalid number of operands!");
1748 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001749 if (isImm()) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001750 addExpr(Inst, getImm());
1751 Inst.addOperand(MCOperand::CreateImm(0));
1752 return;
1753 }
1754
1755 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001756 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1757 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001758 Inst.addOperand(MCOperand::CreateImm(Val));
1759 }
1760
Jim Grosbachd3595712011-08-03 23:50:40 +00001761 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1762 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001763 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001764 if (isImm()) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001765 addExpr(Inst, getImm());
1766 Inst.addOperand(MCOperand::CreateImm(0));
1767 return;
1768 }
1769
1770 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001771 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1772 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001773 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001774 }
Bill Wendling811c9362010-11-30 07:44:32 +00001775
Jim Grosbach05541f42011-09-19 22:21:13 +00001776 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1777 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001778 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1779 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001780 }
1781
1782 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1783 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001784 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1785 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001786 }
1787
Jim Grosbachd3595712011-08-03 23:50:40 +00001788 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1789 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001790 unsigned Val =
1791 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1792 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001793 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1794 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001795 Inst.addOperand(MCOperand::CreateImm(Val));
1796 }
1797
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001798 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1799 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001800 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1801 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1802 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001803 }
1804
Jim Grosbachd3595712011-08-03 23:50:40 +00001805 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1806 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001807 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1808 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001809 }
1810
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001811 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1812 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001813 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1814 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001815 Inst.addOperand(MCOperand::CreateImm(Val));
1816 }
1817
Jim Grosbach26d35872011-08-19 18:55:51 +00001818 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1819 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001820 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1821 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001822 Inst.addOperand(MCOperand::CreateImm(Val));
1823 }
1824
Jim Grosbacha32c7532011-08-19 18:49:59 +00001825 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1826 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001827 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1828 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001829 Inst.addOperand(MCOperand::CreateImm(Val));
1830 }
1831
Jim Grosbach23983d62011-08-19 18:13:48 +00001832 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1833 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001834 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1835 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001836 Inst.addOperand(MCOperand::CreateImm(Val));
1837 }
1838
Jim Grosbachd3595712011-08-03 23:50:40 +00001839 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1840 assert(N == 1 && "Invalid number of operands!");
1841 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1842 assert(CE && "non-constant post-idx-imm8 operand!");
1843 int Imm = CE->getValue();
1844 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001845 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001846 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1847 Inst.addOperand(MCOperand::CreateImm(Imm));
1848 }
1849
Jim Grosbach93981412011-10-11 21:55:36 +00001850 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1851 assert(N == 1 && "Invalid number of operands!");
1852 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1853 assert(CE && "non-constant post-idx-imm8s4 operand!");
1854 int Imm = CE->getValue();
1855 bool isAdd = Imm >= 0;
1856 if (Imm == INT32_MIN) Imm = 0;
1857 // Immediate is scaled by 4.
1858 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1859 Inst.addOperand(MCOperand::CreateImm(Imm));
1860 }
1861
Jim Grosbachd3595712011-08-03 23:50:40 +00001862 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1863 assert(N == 2 && "Invalid number of operands!");
1864 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001865 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1866 }
1867
1868 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1869 assert(N == 2 && "Invalid number of operands!");
1870 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1871 // The sign, shift type, and shift amount are encoded in a single operand
1872 // using the AM2 encoding helpers.
1873 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1874 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1875 PostIdxReg.ShiftTy);
1876 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001877 }
1878
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001879 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1880 assert(N == 1 && "Invalid number of operands!");
1881 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1882 }
1883
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001884 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1885 assert(N == 1 && "Invalid number of operands!");
1886 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1887 }
1888
Jim Grosbach182b6a02011-11-29 23:51:09 +00001889 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001890 assert(N == 1 && "Invalid number of operands!");
1891 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1892 }
1893
Jim Grosbach04945c42011-12-02 00:35:16 +00001894 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1895 assert(N == 2 && "Invalid number of operands!");
1896 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1897 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1898 }
1899
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001900 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1901 assert(N == 1 && "Invalid number of operands!");
1902 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1903 }
1904
1905 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1906 assert(N == 1 && "Invalid number of operands!");
1907 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1908 }
1909
1910 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1911 assert(N == 1 && "Invalid number of operands!");
1912 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1913 }
1914
Jim Grosbach741cd732011-10-17 22:26:03 +00001915 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1916 assert(N == 1 && "Invalid number of operands!");
1917 // The immediate encodes the type of constant as well as the value.
1918 // Mask in that this is an i8 splat.
1919 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1920 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1921 }
1922
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001923 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1924 assert(N == 1 && "Invalid number of operands!");
1925 // The immediate encodes the type of constant as well as the value.
1926 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1927 unsigned Value = CE->getValue();
1928 if (Value >= 256)
1929 Value = (Value >> 8) | 0xa00;
1930 else
1931 Value |= 0x800;
1932 Inst.addOperand(MCOperand::CreateImm(Value));
1933 }
1934
Jim Grosbach8211c052011-10-18 00:22:00 +00001935 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1936 assert(N == 1 && "Invalid number of operands!");
1937 // The immediate encodes the type of constant as well as the value.
1938 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1939 unsigned Value = CE->getValue();
1940 if (Value >= 256 && Value <= 0xff00)
1941 Value = (Value >> 8) | 0x200;
1942 else if (Value > 0xffff && Value <= 0xff0000)
1943 Value = (Value >> 16) | 0x400;
1944 else if (Value > 0xffffff)
1945 Value = (Value >> 24) | 0x600;
1946 Inst.addOperand(MCOperand::CreateImm(Value));
1947 }
1948
1949 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1950 assert(N == 1 && "Invalid number of operands!");
1951 // The immediate encodes the type of constant as well as the value.
1952 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1953 unsigned Value = CE->getValue();
1954 if (Value >= 256 && Value <= 0xffff)
1955 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1956 else if (Value > 0xffff && Value <= 0xffffff)
1957 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1958 else if (Value > 0xffffff)
1959 Value = (Value >> 24) | 0x600;
1960 Inst.addOperand(MCOperand::CreateImm(Value));
1961 }
1962
Jim Grosbach045b6c72011-12-19 23:51:07 +00001963 void addNEONi32vmovNegOperands(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 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1967 unsigned Value = ~CE->getValue();
1968 if (Value >= 256 && Value <= 0xffff)
1969 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1970 else if (Value > 0xffff && Value <= 0xffffff)
1971 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1972 else if (Value > 0xffffff)
1973 Value = (Value >> 24) | 0x600;
1974 Inst.addOperand(MCOperand::CreateImm(Value));
1975 }
1976
Jim Grosbache4454e02011-10-18 16:18:11 +00001977 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1978 assert(N == 1 && "Invalid number of operands!");
1979 // The immediate encodes the type of constant as well as the value.
1980 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1981 uint64_t Value = CE->getValue();
1982 unsigned Imm = 0;
1983 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1984 Imm |= (Value & 1) << i;
1985 }
1986 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1987 }
1988
Jim Grosbach602aa902011-07-13 15:34:57 +00001989 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001990
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001991 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001992 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001993 Op->ITMask.Mask = Mask;
1994 Op->StartLoc = S;
1995 Op->EndLoc = S;
1996 return Op;
1997 }
1998
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001999 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002000 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00002001 Op->CC.Val = CC;
2002 Op->StartLoc = S;
2003 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002004 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00002005 }
2006
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002007 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002008 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002009 Op->Cop.Val = CopVal;
2010 Op->StartLoc = S;
2011 Op->EndLoc = S;
2012 return Op;
2013 }
2014
2015 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002016 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002017 Op->Cop.Val = CopVal;
2018 Op->StartLoc = S;
2019 Op->EndLoc = S;
2020 return Op;
2021 }
2022
Jim Grosbach48399582011-10-12 17:34:41 +00002023 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2024 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2025 Op->Cop.Val = Val;
2026 Op->StartLoc = S;
2027 Op->EndLoc = E;
2028 return Op;
2029 }
2030
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002031 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002032 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002033 Op->Reg.RegNum = RegNum;
2034 Op->StartLoc = S;
2035 Op->EndLoc = S;
2036 return Op;
2037 }
2038
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002039 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002040 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002041 Op->Tok.Data = Str.data();
2042 Op->Tok.Length = Str.size();
2043 Op->StartLoc = S;
2044 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002045 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002046 }
2047
Bill Wendling2063b842010-11-18 23:43:05 +00002048 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002049 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002050 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002051 Op->StartLoc = S;
2052 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002053 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002054 }
2055
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002056 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2057 unsigned SrcReg,
2058 unsigned ShiftReg,
2059 unsigned ShiftImm,
2060 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002061 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00002062 Op->RegShiftedReg.ShiftTy = ShTy;
2063 Op->RegShiftedReg.SrcReg = SrcReg;
2064 Op->RegShiftedReg.ShiftReg = ShiftReg;
2065 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002066 Op->StartLoc = S;
2067 Op->EndLoc = E;
2068 return Op;
2069 }
2070
Owen Andersonb595ed02011-07-21 18:54:16 +00002071 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2072 unsigned SrcReg,
2073 unsigned ShiftImm,
2074 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002075 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00002076 Op->RegShiftedImm.ShiftTy = ShTy;
2077 Op->RegShiftedImm.SrcReg = SrcReg;
2078 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00002079 Op->StartLoc = S;
2080 Op->EndLoc = E;
2081 return Op;
2082 }
2083
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002084 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002085 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002086 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002087 Op->ShifterImm.isASR = isASR;
2088 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002089 Op->StartLoc = S;
2090 Op->EndLoc = E;
2091 return Op;
2092 }
2093
Jim Grosbach833b9d32011-07-27 20:15:40 +00002094 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002095 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00002096 Op->RotImm.Imm = Imm;
2097 Op->StartLoc = S;
2098 Op->EndLoc = E;
2099 return Op;
2100 }
2101
Jim Grosbach864b6092011-07-28 21:34:26 +00002102 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2103 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002104 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00002105 Op->Bitfield.LSB = LSB;
2106 Op->Bitfield.Width = Width;
2107 Op->StartLoc = S;
2108 Op->EndLoc = E;
2109 return Op;
2110 }
2111
Bill Wendling2cae3272010-11-09 22:44:22 +00002112 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00002113 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002114 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002115 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002116
Jim Grosbach75461af2011-09-13 22:56:44 +00002117 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002118 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00002119 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00002120 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002121 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002122
2123 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00002124 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002125 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00002126 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00002127 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002128 Op->StartLoc = StartLoc;
2129 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00002130 return Op;
2131 }
2132
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002133 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach2f50e922011-12-15 21:44:33 +00002134 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002135 ARMOperand *Op = new ARMOperand(k_VectorList);
2136 Op->VectorList.RegNum = RegNum;
2137 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002138 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002139 Op->StartLoc = S;
2140 Op->EndLoc = E;
2141 return Op;
2142 }
2143
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002144 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002145 bool isDoubleSpaced,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002146 SMLoc S, SMLoc E) {
2147 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2148 Op->VectorList.RegNum = RegNum;
2149 Op->VectorList.Count = Count;
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002150 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002151 Op->StartLoc = S;
2152 Op->EndLoc = E;
2153 return Op;
2154 }
2155
Jim Grosbach04945c42011-12-02 00:35:16 +00002156 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002157 unsigned Index,
2158 bool isDoubleSpaced,
2159 SMLoc S, SMLoc E) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002160 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2161 Op->VectorList.RegNum = RegNum;
2162 Op->VectorList.Count = Count;
2163 Op->VectorList.LaneIndex = Index;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002164 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach04945c42011-12-02 00:35:16 +00002165 Op->StartLoc = S;
2166 Op->EndLoc = E;
2167 return Op;
2168 }
2169
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002170 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2171 MCContext &Ctx) {
2172 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2173 Op->VectorIndex.Val = Idx;
2174 Op->StartLoc = S;
2175 Op->EndLoc = E;
2176 return Op;
2177 }
2178
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002179 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002180 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002181 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002182 Op->StartLoc = S;
2183 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002184 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002185 }
2186
Jim Grosbachd3595712011-08-03 23:50:40 +00002187 static ARMOperand *CreateMem(unsigned BaseRegNum,
2188 const MCConstantExpr *OffsetImm,
2189 unsigned OffsetRegNum,
2190 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002191 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002192 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002193 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002194 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002195 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002196 Op->Memory.BaseRegNum = BaseRegNum;
2197 Op->Memory.OffsetImm = OffsetImm;
2198 Op->Memory.OffsetRegNum = OffsetRegNum;
2199 Op->Memory.ShiftType = ShiftType;
2200 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002201 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002202 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002203 Op->StartLoc = S;
2204 Op->EndLoc = E;
2205 return Op;
2206 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002207
Jim Grosbachc320c852011-08-05 21:28:30 +00002208 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2209 ARM_AM::ShiftOpc ShiftTy,
2210 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002211 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002212 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002213 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002214 Op->PostIdxReg.isAdd = isAdd;
2215 Op->PostIdxReg.ShiftTy = ShiftTy;
2216 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002217 Op->StartLoc = S;
2218 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002219 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002220 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002221
2222 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002223 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002224 Op->MBOpt.Val = Opt;
2225 Op->StartLoc = S;
2226 Op->EndLoc = S;
2227 return Op;
2228 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002229
2230 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002231 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002232 Op->IFlags.Val = IFlags;
2233 Op->StartLoc = S;
2234 Op->EndLoc = S;
2235 return Op;
2236 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002237
2238 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002239 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002240 Op->MMask.Val = MMask;
2241 Op->StartLoc = S;
2242 Op->EndLoc = S;
2243 return Op;
2244 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002245};
2246
2247} // end anonymous namespace.
2248
Jim Grosbach602aa902011-07-13 15:34:57 +00002249void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002250 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002251 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002252 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002253 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002254 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002255 OS << "<ccout " << getReg() << ">";
2256 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002257 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002258 static const char *MaskStr[] = {
2259 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2260 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2261 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002262 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2263 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2264 break;
2265 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002266 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002267 OS << "<coprocessor number: " << getCoproc() << ">";
2268 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002269 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002270 OS << "<coprocessor register: " << getCoproc() << ">";
2271 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002272 case k_CoprocOption:
2273 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2274 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002275 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002276 OS << "<mask: " << getMSRMask() << ">";
2277 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002278 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002279 getImm()->print(OS);
2280 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002281 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002282 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2283 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002284 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002285 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002286 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002287 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002288 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002289 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002290 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2291 << PostIdxReg.RegNum;
2292 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2293 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2294 << PostIdxReg.ShiftImm;
2295 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002296 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002297 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002298 OS << "<ARM_PROC::";
2299 unsigned IFlags = getProcIFlags();
2300 for (int i=2; i >= 0; --i)
2301 if (IFlags & (1 << i))
2302 OS << ARM_PROC::IFlagsToString(1 << i);
2303 OS << ">";
2304 break;
2305 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002306 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002307 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002308 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002309 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002310 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2311 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002312 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002313 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002314 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002315 << RegShiftedReg.SrcReg << " "
2316 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2317 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002318 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002319 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002320 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002321 << RegShiftedImm.SrcReg << " "
2322 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2323 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002324 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002325 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002326 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2327 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002328 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002329 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2330 << ", width: " << Bitfield.Width << ">";
2331 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002332 case k_RegisterList:
2333 case k_DPRRegisterList:
2334 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002335 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002336
Bill Wendlingbed94652010-11-09 23:28:44 +00002337 const SmallVectorImpl<unsigned> &RegList = getRegList();
2338 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002339 I = RegList.begin(), E = RegList.end(); I != E; ) {
2340 OS << *I;
2341 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002342 }
2343
2344 OS << ">";
2345 break;
2346 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002347 case k_VectorList:
2348 OS << "<vector_list " << VectorList.Count << " * "
2349 << VectorList.RegNum << ">";
2350 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002351 case k_VectorListAllLanes:
2352 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2353 << VectorList.RegNum << ">";
2354 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002355 case k_VectorListIndexed:
2356 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2357 << VectorList.Count << " * " << VectorList.RegNum << ">";
2358 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002359 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002360 OS << "'" << getToken() << "'";
2361 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002362 case k_VectorIndex:
2363 OS << "<vectorindex " << getVectorIndex() << ">";
2364 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002365 }
2366}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002367
2368/// @name Auto-generated Match Functions
2369/// {
2370
2371static unsigned MatchRegisterName(StringRef Name);
2372
2373/// }
2374
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002375bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2376 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002377 StartLoc = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002378 RegNo = tryParseRegister();
Jim Grosbachab5830e2011-12-14 02:16:11 +00002379 EndLoc = Parser.getTok().getLoc();
Roman Divacky36b1b472011-01-27 17:14:22 +00002380
2381 return (RegNo == (unsigned)-1);
2382}
2383
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002384/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002385/// and if it is a register name the token is eaten and the register number is
2386/// returned. Otherwise return -1.
2387///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002388int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002389 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002390 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002391
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002392 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002393 unsigned RegNum = MatchRegisterName(lowerCase);
2394 if (!RegNum) {
2395 RegNum = StringSwitch<unsigned>(lowerCase)
2396 .Case("r13", ARM::SP)
2397 .Case("r14", ARM::LR)
2398 .Case("r15", ARM::PC)
2399 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002400 // Additional register name aliases for 'gas' compatibility.
2401 .Case("a1", ARM::R0)
2402 .Case("a2", ARM::R1)
2403 .Case("a3", ARM::R2)
2404 .Case("a4", ARM::R3)
2405 .Case("v1", ARM::R4)
2406 .Case("v2", ARM::R5)
2407 .Case("v3", ARM::R6)
2408 .Case("v4", ARM::R7)
2409 .Case("v5", ARM::R8)
2410 .Case("v6", ARM::R9)
2411 .Case("v7", ARM::R10)
2412 .Case("v8", ARM::R11)
2413 .Case("sb", ARM::R9)
2414 .Case("sl", ARM::R10)
2415 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002416 .Default(0);
2417 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002418 if (!RegNum) {
Jim Grosbachcd22e4a2011-12-20 23:11:00 +00002419 // Check for aliases registered via .req. Canonicalize to lower case.
2420 // That's more consistent since register names are case insensitive, and
2421 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2422 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbachab5830e2011-12-14 02:16:11 +00002423 // If no match, return failure.
2424 if (Entry == RegisterReqs.end())
2425 return -1;
2426 Parser.Lex(); // Eat identifier token.
2427 return Entry->getValue();
2428 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002429
Chris Lattner44e5981c2010-10-30 04:09:10 +00002430 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002431
Chris Lattner44e5981c2010-10-30 04:09:10 +00002432 return RegNum;
2433}
Jim Grosbach99710a82010-11-01 16:44:21 +00002434
Jim Grosbachbb24c592011-07-13 18:49:30 +00002435// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2436// If a recoverable error occurs, return 1. If an irrecoverable error
2437// occurs, return -1. An irrecoverable error is one where tokens have been
2438// consumed in the process of trying to parse the shifter (i.e., when it is
2439// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002440int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002441 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2442 SMLoc S = Parser.getTok().getLoc();
2443 const AsmToken &Tok = Parser.getTok();
2444 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2445
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002446 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002447 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002448 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002449 .Case("lsl", ARM_AM::lsl)
2450 .Case("lsr", ARM_AM::lsr)
2451 .Case("asr", ARM_AM::asr)
2452 .Case("ror", ARM_AM::ror)
2453 .Case("rrx", ARM_AM::rrx)
2454 .Default(ARM_AM::no_shift);
2455
2456 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002457 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002458
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002459 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002460
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002461 // The source register for the shift has already been added to the
2462 // operand list, so we need to pop it off and combine it into the shifted
2463 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002464 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002465 if (!PrevOp->isReg())
2466 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2467 int SrcReg = PrevOp->getReg();
2468 int64_t Imm = 0;
2469 int ShiftReg = 0;
2470 if (ShiftTy == ARM_AM::rrx) {
2471 // RRX Doesn't have an explicit shift amount. The encoder expects
2472 // the shift register to be the same as the source register. Seems odd,
2473 // but OK.
2474 ShiftReg = SrcReg;
2475 } else {
2476 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002477 if (Parser.getTok().is(AsmToken::Hash) ||
2478 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002479 Parser.Lex(); // Eat hash.
2480 SMLoc ImmLoc = Parser.getTok().getLoc();
2481 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002482 if (getParser().ParseExpression(ShiftExpr)) {
2483 Error(ImmLoc, "invalid immediate shift value");
2484 return -1;
2485 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002486 // The expression must be evaluatable as an immediate.
2487 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002488 if (!CE) {
2489 Error(ImmLoc, "invalid immediate shift value");
2490 return -1;
2491 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002492 // Range check the immediate.
2493 // lsl, ror: 0 <= imm <= 31
2494 // lsr, asr: 0 <= imm <= 32
2495 Imm = CE->getValue();
2496 if (Imm < 0 ||
2497 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2498 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002499 Error(ImmLoc, "immediate shift value out of range");
2500 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002501 }
Jim Grosbach21488b82011-12-22 17:37:00 +00002502 // shift by zero is a nop. Always send it through as lsl.
2503 // ('as' compatibility)
2504 if (Imm == 0)
2505 ShiftTy = ARM_AM::lsl;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002506 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002507 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002508 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002509 if (ShiftReg == -1) {
2510 Error (L, "expected immediate or register in shift operand");
2511 return -1;
2512 }
2513 } else {
2514 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002515 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002516 return -1;
2517 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002518 }
2519
Owen Andersonb595ed02011-07-21 18:54:16 +00002520 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2521 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002522 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002523 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002524 else
2525 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2526 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002527
Jim Grosbachbb24c592011-07-13 18:49:30 +00002528 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002529}
2530
2531
Bill Wendling2063b842010-11-18 23:43:05 +00002532/// Try to parse a register name. The token must be an Identifier when called.
2533/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2534/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002535///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002536/// TODO this is likely to change to allow different register types and or to
2537/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002538bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002539tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002540 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002541 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002542 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002543 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002544
Bill Wendling2063b842010-11-18 23:43:05 +00002545 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002546
Chris Lattner44e5981c2010-10-30 04:09:10 +00002547 const AsmToken &ExclaimTok = Parser.getTok();
2548 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002549 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2550 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002551 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002552 return false;
2553 }
2554
2555 // Also check for an index operand. This is only legal for vector registers,
2556 // but that'll get caught OK in operand matching, so we don't need to
2557 // explicitly filter everything else out here.
2558 if (Parser.getTok().is(AsmToken::LBrac)) {
2559 SMLoc SIdx = Parser.getTok().getLoc();
2560 Parser.Lex(); // Eat left bracket token.
2561
2562 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002563 if (getParser().ParseExpression(ImmVal))
Jim Grosbacha2147ce2012-01-31 23:51:09 +00002564 return true;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002565 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachc8f2b782012-01-26 15:56:45 +00002566 if (!MCE)
2567 return TokError("immediate value expected for vector index");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002568
2569 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachc8f2b782012-01-26 15:56:45 +00002570 if (Parser.getTok().isNot(AsmToken::RBrac))
2571 return Error(E, "']' expected");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002572
2573 Parser.Lex(); // Eat right bracket token.
2574
2575 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2576 SIdx, E,
2577 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002578 }
2579
Bill Wendling2063b842010-11-18 23:43:05 +00002580 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002581}
2582
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002583/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2584/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2585/// "c5", ...
2586static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002587 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2588 // but efficient.
2589 switch (Name.size()) {
David Blaikie46a9f012012-01-20 21:51:11 +00002590 default: return -1;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002591 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002592 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002593 return -1;
2594 switch (Name[1]) {
2595 default: return -1;
2596 case '0': return 0;
2597 case '1': return 1;
2598 case '2': return 2;
2599 case '3': return 3;
2600 case '4': return 4;
2601 case '5': return 5;
2602 case '6': return 6;
2603 case '7': return 7;
2604 case '8': return 8;
2605 case '9': return 9;
2606 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002607 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002608 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002609 return -1;
2610 switch (Name[2]) {
2611 default: return -1;
2612 case '0': return 10;
2613 case '1': return 11;
2614 case '2': return 12;
2615 case '3': return 13;
2616 case '4': return 14;
2617 case '5': return 15;
2618 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002619 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002620}
2621
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002622/// parseITCondCode - Try to parse a condition code for an IT instruction.
2623ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2624parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2625 SMLoc S = Parser.getTok().getLoc();
2626 const AsmToken &Tok = Parser.getTok();
2627 if (!Tok.is(AsmToken::Identifier))
2628 return MatchOperand_NoMatch;
2629 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2630 .Case("eq", ARMCC::EQ)
2631 .Case("ne", ARMCC::NE)
2632 .Case("hs", ARMCC::HS)
2633 .Case("cs", ARMCC::HS)
2634 .Case("lo", ARMCC::LO)
2635 .Case("cc", ARMCC::LO)
2636 .Case("mi", ARMCC::MI)
2637 .Case("pl", ARMCC::PL)
2638 .Case("vs", ARMCC::VS)
2639 .Case("vc", ARMCC::VC)
2640 .Case("hi", ARMCC::HI)
2641 .Case("ls", ARMCC::LS)
2642 .Case("ge", ARMCC::GE)
2643 .Case("lt", ARMCC::LT)
2644 .Case("gt", ARMCC::GT)
2645 .Case("le", ARMCC::LE)
2646 .Case("al", ARMCC::AL)
2647 .Default(~0U);
2648 if (CC == ~0U)
2649 return MatchOperand_NoMatch;
2650 Parser.Lex(); // Eat the token.
2651
2652 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2653
2654 return MatchOperand_Success;
2655}
2656
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002657/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002658/// token must be an Identifier when called, and if it is a coprocessor
2659/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002660ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002661parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002662 SMLoc S = Parser.getTok().getLoc();
2663 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002664 if (Tok.isNot(AsmToken::Identifier))
2665 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002666
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002667 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002668 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002669 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002670
2671 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002672 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002673 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002674}
2675
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002676/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002677/// token must be an Identifier when called, and if it is a coprocessor
2678/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002679ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002680parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002681 SMLoc S = Parser.getTok().getLoc();
2682 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002683 if (Tok.isNot(AsmToken::Identifier))
2684 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002685
2686 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2687 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002688 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002689
2690 Parser.Lex(); // Eat identifier token.
2691 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002692 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002693}
2694
Jim Grosbach48399582011-10-12 17:34:41 +00002695/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2696/// coproc_option : '{' imm0_255 '}'
2697ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2698parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2699 SMLoc S = Parser.getTok().getLoc();
2700
2701 // If this isn't a '{', this isn't a coprocessor immediate operand.
2702 if (Parser.getTok().isNot(AsmToken::LCurly))
2703 return MatchOperand_NoMatch;
2704 Parser.Lex(); // Eat the '{'
2705
2706 const MCExpr *Expr;
2707 SMLoc Loc = Parser.getTok().getLoc();
2708 if (getParser().ParseExpression(Expr)) {
2709 Error(Loc, "illegal expression");
2710 return MatchOperand_ParseFail;
2711 }
2712 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2713 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2714 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2715 return MatchOperand_ParseFail;
2716 }
2717 int Val = CE->getValue();
2718
2719 // Check for and consume the closing '}'
2720 if (Parser.getTok().isNot(AsmToken::RCurly))
2721 return MatchOperand_ParseFail;
2722 SMLoc E = Parser.getTok().getLoc();
2723 Parser.Lex(); // Eat the '}'
2724
2725 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2726 return MatchOperand_Success;
2727}
2728
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002729// For register list parsing, we need to map from raw GPR register numbering
2730// to the enumeration values. The enumeration values aren't sorted by
2731// register number due to our using "sp", "lr" and "pc" as canonical names.
2732static unsigned getNextRegister(unsigned Reg) {
2733 // If this is a GPR, we need to do it manually, otherwise we can rely
2734 // on the sort ordering of the enumeration since the other reg-classes
2735 // are sane.
2736 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2737 return Reg + 1;
2738 switch(Reg) {
Craig Toppere55c5562012-02-07 02:50:20 +00002739 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002740 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2741 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2742 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2743 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2744 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2745 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2746 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2747 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2748 }
2749}
2750
Jim Grosbach85a23432011-11-11 21:27:40 +00002751// Return the low-subreg of a given Q register.
2752static unsigned getDRegFromQReg(unsigned QReg) {
2753 switch (QReg) {
2754 default: llvm_unreachable("expected a Q register!");
2755 case ARM::Q0: return ARM::D0;
2756 case ARM::Q1: return ARM::D2;
2757 case ARM::Q2: return ARM::D4;
2758 case ARM::Q3: return ARM::D6;
2759 case ARM::Q4: return ARM::D8;
2760 case ARM::Q5: return ARM::D10;
2761 case ARM::Q6: return ARM::D12;
2762 case ARM::Q7: return ARM::D14;
2763 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002764 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002765 case ARM::Q10: return ARM::D20;
2766 case ARM::Q11: return ARM::D22;
2767 case ARM::Q12: return ARM::D24;
2768 case ARM::Q13: return ARM::D26;
2769 case ARM::Q14: return ARM::D28;
2770 case ARM::Q15: return ARM::D30;
2771 }
2772}
2773
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002774/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002775bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002776parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002777 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002778 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002779 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002780 Parser.Lex(); // Eat '{' token.
2781 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002782
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002783 // Check the first register in the list to see what register class
2784 // this is a list of.
2785 int Reg = tryParseRegister();
2786 if (Reg == -1)
2787 return Error(RegLoc, "register expected");
2788
Jim Grosbach85a23432011-11-11 21:27:40 +00002789 // The reglist instructions have at most 16 registers, so reserve
2790 // space for that many.
2791 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2792
2793 // Allow Q regs and just interpret them as the two D sub-registers.
2794 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2795 Reg = getDRegFromQReg(Reg);
2796 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2797 ++Reg;
2798 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002799 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002800 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2801 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2802 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2803 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2804 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2805 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2806 else
2807 return Error(RegLoc, "invalid register in register list");
2808
Jim Grosbach85a23432011-11-11 21:27:40 +00002809 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002810 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002811
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002812 // This starts immediately after the first register token in the list,
2813 // so we can see either a comma or a minus (range separator) as a legal
2814 // next token.
2815 while (Parser.getTok().is(AsmToken::Comma) ||
2816 Parser.getTok().is(AsmToken::Minus)) {
2817 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002818 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002819 SMLoc EndLoc = Parser.getTok().getLoc();
2820 int EndReg = tryParseRegister();
2821 if (EndReg == -1)
2822 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002823 // Allow Q regs and just interpret them as the two D sub-registers.
2824 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2825 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002826 // If the register is the same as the start reg, there's nothing
2827 // more to do.
2828 if (Reg == EndReg)
2829 continue;
2830 // The register must be in the same register class as the first.
2831 if (!RC->contains(EndReg))
2832 return Error(EndLoc, "invalid register in register list");
2833 // Ranges must go from low to high.
2834 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2835 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002836
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002837 // Add all the registers in the range to the register list.
2838 while (Reg != EndReg) {
2839 Reg = getNextRegister(Reg);
2840 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2841 }
2842 continue;
2843 }
2844 Parser.Lex(); // Eat the comma.
2845 RegLoc = Parser.getTok().getLoc();
2846 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002847 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002848 Reg = tryParseRegister();
2849 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002850 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002851 // Allow Q regs and just interpret them as the two D sub-registers.
2852 bool isQReg = false;
2853 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2854 Reg = getDRegFromQReg(Reg);
2855 isQReg = true;
2856 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002857 // The register must be in the same register class as the first.
2858 if (!RC->contains(Reg))
2859 return Error(RegLoc, "invalid register in register list");
2860 // List must be monotonically increasing.
Jim Grosbach905686a2012-03-16 20:48:38 +00002861 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2862 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2863 Warning(RegLoc, "register list not in ascending order");
2864 else
2865 return Error(RegLoc, "register list not in ascending order");
2866 }
Jim Grosbach98bc7972011-12-08 21:34:20 +00002867 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2868 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2869 ") in register list");
2870 continue;
2871 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002872 // VFP register lists must also be contiguous.
2873 // It's OK to use the enumeration values directly here rather, as the
2874 // VFP register classes have the enum sorted properly.
2875 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2876 Reg != OldReg + 1)
2877 return Error(RegLoc, "non-contiguous register range");
2878 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002879 if (isQReg)
2880 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002881 }
2882
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002883 SMLoc E = Parser.getTok().getLoc();
2884 if (Parser.getTok().isNot(AsmToken::RCurly))
2885 return Error(E, "'}' expected");
2886 Parser.Lex(); // Eat '}' token.
2887
Jim Grosbach18bf3632011-12-13 21:48:29 +00002888 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002889 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002890
2891 // The ARM system instruction variants for LDM/STM have a '^' token here.
2892 if (Parser.getTok().is(AsmToken::Caret)) {
2893 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2894 Parser.Lex(); // Eat '^' token.
2895 }
2896
Bill Wendling2063b842010-11-18 23:43:05 +00002897 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002898}
2899
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002900// Helper function to parse the lane index for vector lists.
2901ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002902parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2903 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002904 if (Parser.getTok().is(AsmToken::LBrac)) {
2905 Parser.Lex(); // Eat the '['.
2906 if (Parser.getTok().is(AsmToken::RBrac)) {
2907 // "Dn[]" is the 'all lanes' syntax.
2908 LaneKind = AllLanes;
2909 Parser.Lex(); // Eat the ']'.
2910 return MatchOperand_Success;
2911 }
Jim Grosbach67e76ba2012-03-19 20:39:53 +00002912
2913 // There's an optional '#' token here. Normally there wouldn't be, but
2914 // inline assemble puts one in, and it's friendly to accept that.
2915 if (Parser.getTok().is(AsmToken::Hash))
2916 Parser.Lex(); // Eat the '#'
2917
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002918 const MCExpr *LaneIndex;
2919 SMLoc Loc = Parser.getTok().getLoc();
2920 if (getParser().ParseExpression(LaneIndex)) {
2921 Error(Loc, "illegal expression");
2922 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002923 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2925 if (!CE) {
2926 Error(Loc, "lane index must be empty or an integer");
2927 return MatchOperand_ParseFail;
2928 }
2929 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2930 Error(Parser.getTok().getLoc(), "']' expected");
2931 return MatchOperand_ParseFail;
2932 }
2933 Parser.Lex(); // Eat the ']'.
2934 int64_t Val = CE->getValue();
2935
2936 // FIXME: Make this range check context sensitive for .8, .16, .32.
2937 if (Val < 0 || Val > 7) {
2938 Error(Parser.getTok().getLoc(), "lane index out of range");
2939 return MatchOperand_ParseFail;
2940 }
2941 Index = Val;
2942 LaneKind = IndexedLane;
2943 return MatchOperand_Success;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002944 }
2945 LaneKind = NoLanes;
2946 return MatchOperand_Success;
2947}
2948
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002949// parse a vector register list
2950ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2951parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002952 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002953 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002954 SMLoc S = Parser.getTok().getLoc();
2955 // As an extension (to match gas), support a plain D register or Q register
2956 // (without encosing curly braces) as a single or double entry list,
2957 // respectively.
2958 if (Parser.getTok().is(AsmToken::Identifier)) {
2959 int Reg = tryParseRegister();
2960 if (Reg == -1)
2961 return MatchOperand_NoMatch;
2962 SMLoc E = Parser.getTok().getLoc();
2963 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002964 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002965 if (Res != MatchOperand_Success)
2966 return Res;
2967 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002968 case NoLanes:
2969 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002970 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002971 break;
2972 case AllLanes:
2973 E = Parser.getTok().getLoc();
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002974 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2975 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002976 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002977 case IndexedLane:
2978 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002979 LaneIndex,
2980 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002981 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002982 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002983 return MatchOperand_Success;
2984 }
2985 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2986 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002987 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002988 if (Res != MatchOperand_Success)
2989 return Res;
2990 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002991 case NoLanes:
2992 E = Parser.getTok().getLoc();
Jim Grosbachc988e0c2012-03-05 19:33:30 +00002993 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbach13a292c2012-03-06 22:01:44 +00002994 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach2f50e922011-12-15 21:44:33 +00002995 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002996 break;
2997 case AllLanes:
2998 E = Parser.getTok().getLoc();
Jim Grosbach13a292c2012-03-06 22:01:44 +00002999 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3000 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003001 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3002 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003003 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003004 case IndexedLane:
3005 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003006 LaneIndex,
3007 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003008 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003009 }
Jim Grosbach8d579232011-11-15 21:45:55 +00003010 return MatchOperand_Success;
3011 }
3012 Error(S, "vector register expected");
3013 return MatchOperand_ParseFail;
3014 }
3015
3016 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003017 return MatchOperand_NoMatch;
3018
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003019 Parser.Lex(); // Eat '{' token.
3020 SMLoc RegLoc = Parser.getTok().getLoc();
3021
3022 int Reg = tryParseRegister();
3023 if (Reg == -1) {
3024 Error(RegLoc, "register expected");
3025 return MatchOperand_ParseFail;
3026 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003027 unsigned Count = 1;
Jim Grosbachc2f16a32011-12-15 21:54:55 +00003028 int Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00003029 unsigned FirstReg = Reg;
3030 // The list is of D registers, but we also allow Q regs and just interpret
3031 // them as the two D sub-registers.
3032 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3033 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00003034 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3035 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00003036 ++Reg;
3037 ++Count;
3038 }
Jim Grosbach04945c42011-12-02 00:35:16 +00003039 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003040 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00003041
Jim Grosbache891fe82011-11-15 23:19:15 +00003042 while (Parser.getTok().is(AsmToken::Comma) ||
3043 Parser.getTok().is(AsmToken::Minus)) {
3044 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003045 if (!Spacing)
3046 Spacing = 1; // Register range implies a single spaced list.
3047 else if (Spacing == 2) {
3048 Error(Parser.getTok().getLoc(),
3049 "sequential registers in double spaced list");
3050 return MatchOperand_ParseFail;
3051 }
Jim Grosbache891fe82011-11-15 23:19:15 +00003052 Parser.Lex(); // Eat the minus.
3053 SMLoc EndLoc = Parser.getTok().getLoc();
3054 int EndReg = tryParseRegister();
3055 if (EndReg == -1) {
3056 Error(EndLoc, "register expected");
3057 return MatchOperand_ParseFail;
3058 }
3059 // Allow Q regs and just interpret them as the two D sub-registers.
3060 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3061 EndReg = getDRegFromQReg(EndReg) + 1;
3062 // If the register is the same as the start reg, there's nothing
3063 // more to do.
3064 if (Reg == EndReg)
3065 continue;
3066 // The register must be in the same register class as the first.
3067 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3068 Error(EndLoc, "invalid register in register list");
3069 return MatchOperand_ParseFail;
3070 }
3071 // Ranges must go from low to high.
3072 if (Reg > EndReg) {
3073 Error(EndLoc, "bad range in register list");
3074 return MatchOperand_ParseFail;
3075 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003076 // Parse the lane specifier if present.
3077 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003078 unsigned NextLaneIndex;
3079 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003080 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003081 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003082 Error(EndLoc, "mismatched lane index in register list");
3083 return MatchOperand_ParseFail;
3084 }
3085 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00003086
3087 // Add all the registers in the range to the register list.
3088 Count += EndReg - Reg;
3089 Reg = EndReg;
3090 continue;
3091 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003092 Parser.Lex(); // Eat the comma.
3093 RegLoc = Parser.getTok().getLoc();
3094 int OldReg = Reg;
3095 Reg = tryParseRegister();
3096 if (Reg == -1) {
3097 Error(RegLoc, "register expected");
3098 return MatchOperand_ParseFail;
3099 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003100 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003101 // It's OK to use the enumeration values directly here rather, as the
3102 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00003103 //
3104 // The list is of D registers, but we also allow Q regs and just interpret
3105 // them as the two D sub-registers.
3106 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003107 if (!Spacing)
3108 Spacing = 1; // Register range implies a single spaced list.
3109 else if (Spacing == 2) {
3110 Error(RegLoc,
3111 "invalid register in double-spaced list (must be 'D' register')");
3112 return MatchOperand_ParseFail;
3113 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003114 Reg = getDRegFromQReg(Reg);
3115 if (Reg != OldReg + 1) {
3116 Error(RegLoc, "non-contiguous register range");
3117 return MatchOperand_ParseFail;
3118 }
3119 ++Reg;
3120 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003121 // Parse the lane specifier if present.
3122 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003123 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003124 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003125 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003126 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003127 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003128 Error(EndLoc, "mismatched lane index in register list");
3129 return MatchOperand_ParseFail;
3130 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003131 continue;
3132 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00003133 // Normal D register.
3134 // Figure out the register spacing (single or double) of the list if
3135 // we don't know it already.
3136 if (!Spacing)
3137 Spacing = 1 + (Reg == OldReg + 2);
3138
3139 // Just check that it's contiguous and keep going.
3140 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003141 Error(RegLoc, "non-contiguous register range");
3142 return MatchOperand_ParseFail;
3143 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003144 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003145 // Parse the lane specifier if present.
3146 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003147 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003148 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003149 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003150 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003151 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003152 Error(EndLoc, "mismatched lane index in register list");
3153 return MatchOperand_ParseFail;
3154 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003155 }
3156
3157 SMLoc E = Parser.getTok().getLoc();
3158 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3159 Error(E, "'}' expected");
3160 return MatchOperand_ParseFail;
3161 }
3162 Parser.Lex(); // Eat '}' token.
3163
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003164 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003165 case NoLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003166 // Two-register operands have been converted to the
Jim Grosbache5307f92012-03-05 21:43:40 +00003167 // composite register classes.
3168 if (Count == 2) {
3169 const MCRegisterClass *RC = (Spacing == 1) ?
3170 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3171 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3172 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3173 }
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003174
Jim Grosbach2f50e922011-12-15 21:44:33 +00003175 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3176 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003177 break;
3178 case AllLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003179 // Two-register operands have been converted to the
3180 // composite register classes.
Jim Grosbached428bc2012-03-06 23:10:38 +00003181 if (Count == 2) {
3182 const MCRegisterClass *RC = (Spacing == 1) ?
3183 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3184 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbach13a292c2012-03-06 22:01:44 +00003185 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3186 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003187 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003188 (Spacing == 2),
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003189 S, E));
3190 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003191 case IndexedLane:
3192 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003193 LaneIndex,
3194 (Spacing == 2),
3195 S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003196 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003197 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003198 return MatchOperand_Success;
3199}
3200
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003201/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003202ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003203parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003204 SMLoc S = Parser.getTok().getLoc();
3205 const AsmToken &Tok = Parser.getTok();
3206 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3207 StringRef OptStr = Tok.getString();
3208
3209 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3210 .Case("sy", ARM_MB::SY)
3211 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003212 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003213 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003214 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003215 .Case("ishst", ARM_MB::ISHST)
3216 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003217 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003218 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003219 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003220 .Case("osh", ARM_MB::OSH)
3221 .Case("oshst", ARM_MB::OSHST)
3222 .Default(~0U);
3223
3224 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003225 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003226
3227 Parser.Lex(); // Eat identifier token.
3228 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003229 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003230}
3231
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003232/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003233ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003234parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003235 SMLoc S = Parser.getTok().getLoc();
3236 const AsmToken &Tok = Parser.getTok();
3237 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3238 StringRef IFlagsStr = Tok.getString();
3239
Owen Anderson10c5b122011-10-05 17:16:40 +00003240 // An iflags string of "none" is interpreted to mean that none of the AIF
3241 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003242 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003243 if (IFlagsStr != "none") {
3244 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3245 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3246 .Case("a", ARM_PROC::A)
3247 .Case("i", ARM_PROC::I)
3248 .Case("f", ARM_PROC::F)
3249 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003250
Owen Anderson10c5b122011-10-05 17:16:40 +00003251 // If some specific iflag is already set, it means that some letter is
3252 // present more than once, this is not acceptable.
3253 if (Flag == ~0U || (IFlags & Flag))
3254 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003255
Owen Anderson10c5b122011-10-05 17:16:40 +00003256 IFlags |= Flag;
3257 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003258 }
3259
3260 Parser.Lex(); // Eat identifier token.
3261 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3262 return MatchOperand_Success;
3263}
3264
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003265/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003266ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003267parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003268 SMLoc S = Parser.getTok().getLoc();
3269 const AsmToken &Tok = Parser.getTok();
3270 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3271 StringRef Mask = Tok.getString();
3272
James Molloy21efa7d2011-09-28 14:21:38 +00003273 if (isMClass()) {
3274 // See ARMv6-M 10.1.1
Jim Grosbachd28888d2012-03-15 21:34:14 +00003275 std::string Name = Mask.lower();
3276 unsigned FlagsVal = StringSwitch<unsigned>(Name)
James Molloy21efa7d2011-09-28 14:21:38 +00003277 .Case("apsr", 0)
3278 .Case("iapsr", 1)
3279 .Case("eapsr", 2)
3280 .Case("xpsr", 3)
3281 .Case("ipsr", 5)
3282 .Case("epsr", 6)
3283 .Case("iepsr", 7)
3284 .Case("msp", 8)
3285 .Case("psp", 9)
3286 .Case("primask", 16)
3287 .Case("basepri", 17)
3288 .Case("basepri_max", 18)
3289 .Case("faultmask", 19)
3290 .Case("control", 20)
3291 .Default(~0U);
Jim Grosbach3794d822011-12-22 17:17:10 +00003292
James Molloy21efa7d2011-09-28 14:21:38 +00003293 if (FlagsVal == ~0U)
3294 return MatchOperand_NoMatch;
3295
3296 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3297 // basepri, basepri_max and faultmask only valid for V7m.
3298 return MatchOperand_NoMatch;
Jim Grosbach3794d822011-12-22 17:17:10 +00003299
James Molloy21efa7d2011-09-28 14:21:38 +00003300 Parser.Lex(); // Eat identifier token.
3301 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3302 return MatchOperand_Success;
3303 }
3304
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003305 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3306 size_t Start = 0, Next = Mask.find('_');
3307 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003308 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003309 if (Next != StringRef::npos)
3310 Flags = Mask.slice(Next+1, Mask.size());
3311
3312 // FlagsVal contains the complete mask:
3313 // 3-0: Mask
3314 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3315 unsigned FlagsVal = 0;
3316
3317 if (SpecReg == "apsr") {
3318 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003319 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003320 .Case("g", 0x4) // same as CPSR_s
3321 .Case("nzcvqg", 0xc) // same as CPSR_fs
3322 .Default(~0U);
3323
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003324 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003325 if (!Flags.empty())
3326 return MatchOperand_NoMatch;
3327 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003328 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003329 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003330 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003331 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3332 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003333 for (int i = 0, e = Flags.size(); i != e; ++i) {
3334 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3335 .Case("c", 1)
3336 .Case("x", 2)
3337 .Case("s", 4)
3338 .Case("f", 8)
3339 .Default(~0U);
3340
3341 // If some specific flag is already set, it means that some letter is
3342 // present more than once, this is not acceptable.
3343 if (FlagsVal == ~0U || (FlagsVal & Flag))
3344 return MatchOperand_NoMatch;
3345 FlagsVal |= Flag;
3346 }
3347 } else // No match for special register.
3348 return MatchOperand_NoMatch;
3349
Owen Anderson03a173e2011-10-21 18:43:28 +00003350 // Special register without flags is NOT equivalent to "fc" flags.
3351 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3352 // two lines would enable gas compatibility at the expense of breaking
3353 // round-tripping.
3354 //
3355 // if (!FlagsVal)
3356 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003357
3358 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3359 if (SpecReg == "spsr")
3360 FlagsVal |= 16;
3361
3362 Parser.Lex(); // Eat identifier token.
3363 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3364 return MatchOperand_Success;
3365}
3366
Jim Grosbach27c1e252011-07-21 17:23:04 +00003367ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3368parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3369 int Low, int High) {
3370 const AsmToken &Tok = Parser.getTok();
3371 if (Tok.isNot(AsmToken::Identifier)) {
3372 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3373 return MatchOperand_ParseFail;
3374 }
3375 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003376 std::string LowerOp = Op.lower();
3377 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003378 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3379 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3380 return MatchOperand_ParseFail;
3381 }
3382 Parser.Lex(); // Eat shift type token.
3383
3384 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003385 if (Parser.getTok().isNot(AsmToken::Hash) &&
3386 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003387 Error(Parser.getTok().getLoc(), "'#' expected");
3388 return MatchOperand_ParseFail;
3389 }
3390 Parser.Lex(); // Eat hash token.
3391
3392 const MCExpr *ShiftAmount;
3393 SMLoc Loc = Parser.getTok().getLoc();
3394 if (getParser().ParseExpression(ShiftAmount)) {
3395 Error(Loc, "illegal expression");
3396 return MatchOperand_ParseFail;
3397 }
3398 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3399 if (!CE) {
3400 Error(Loc, "constant expression expected");
3401 return MatchOperand_ParseFail;
3402 }
3403 int Val = CE->getValue();
3404 if (Val < Low || Val > High) {
3405 Error(Loc, "immediate value out of range");
3406 return MatchOperand_ParseFail;
3407 }
3408
3409 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3410
3411 return MatchOperand_Success;
3412}
3413
Jim Grosbach0a547702011-07-22 17:44:50 +00003414ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3415parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3416 const AsmToken &Tok = Parser.getTok();
3417 SMLoc S = Tok.getLoc();
3418 if (Tok.isNot(AsmToken::Identifier)) {
3419 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3420 return MatchOperand_ParseFail;
3421 }
3422 int Val = StringSwitch<int>(Tok.getString())
3423 .Case("be", 1)
3424 .Case("le", 0)
3425 .Default(-1);
3426 Parser.Lex(); // Eat the token.
3427
3428 if (Val == -1) {
3429 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3430 return MatchOperand_ParseFail;
3431 }
3432 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3433 getContext()),
3434 S, Parser.getTok().getLoc()));
3435 return MatchOperand_Success;
3436}
3437
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003438/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3439/// instructions. Legal values are:
3440/// lsl #n 'n' in [0,31]
3441/// asr #n 'n' in [1,32]
3442/// n == 32 encoded as n == 0.
3443ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3444parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3445 const AsmToken &Tok = Parser.getTok();
3446 SMLoc S = Tok.getLoc();
3447 if (Tok.isNot(AsmToken::Identifier)) {
3448 Error(S, "shift operator 'asr' or 'lsl' expected");
3449 return MatchOperand_ParseFail;
3450 }
3451 StringRef ShiftName = Tok.getString();
3452 bool isASR;
3453 if (ShiftName == "lsl" || ShiftName == "LSL")
3454 isASR = false;
3455 else if (ShiftName == "asr" || ShiftName == "ASR")
3456 isASR = true;
3457 else {
3458 Error(S, "shift operator 'asr' or 'lsl' expected");
3459 return MatchOperand_ParseFail;
3460 }
3461 Parser.Lex(); // Eat the operator.
3462
3463 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003464 if (Parser.getTok().isNot(AsmToken::Hash) &&
3465 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003466 Error(Parser.getTok().getLoc(), "'#' expected");
3467 return MatchOperand_ParseFail;
3468 }
3469 Parser.Lex(); // Eat hash token.
3470
3471 const MCExpr *ShiftAmount;
3472 SMLoc E = Parser.getTok().getLoc();
3473 if (getParser().ParseExpression(ShiftAmount)) {
3474 Error(E, "malformed shift expression");
3475 return MatchOperand_ParseFail;
3476 }
3477 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3478 if (!CE) {
3479 Error(E, "shift amount must be an immediate");
3480 return MatchOperand_ParseFail;
3481 }
3482
3483 int64_t Val = CE->getValue();
3484 if (isASR) {
3485 // Shift amount must be in [1,32]
3486 if (Val < 1 || Val > 32) {
3487 Error(E, "'asr' shift amount must be in range [1,32]");
3488 return MatchOperand_ParseFail;
3489 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003490 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3491 if (isThumb() && Val == 32) {
3492 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3493 return MatchOperand_ParseFail;
3494 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003495 if (Val == 32) Val = 0;
3496 } else {
3497 // Shift amount must be in [1,32]
3498 if (Val < 0 || Val > 31) {
3499 Error(E, "'lsr' shift amount must be in range [0,31]");
3500 return MatchOperand_ParseFail;
3501 }
3502 }
3503
3504 E = Parser.getTok().getLoc();
3505 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3506
3507 return MatchOperand_Success;
3508}
3509
Jim Grosbach833b9d32011-07-27 20:15:40 +00003510/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3511/// of instructions. Legal values are:
3512/// ror #n 'n' in {0, 8, 16, 24}
3513ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3514parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3515 const AsmToken &Tok = Parser.getTok();
3516 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003517 if (Tok.isNot(AsmToken::Identifier))
3518 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003519 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003520 if (ShiftName != "ror" && ShiftName != "ROR")
3521 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003522 Parser.Lex(); // Eat the operator.
3523
3524 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003525 if (Parser.getTok().isNot(AsmToken::Hash) &&
3526 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003527 Error(Parser.getTok().getLoc(), "'#' expected");
3528 return MatchOperand_ParseFail;
3529 }
3530 Parser.Lex(); // Eat hash token.
3531
3532 const MCExpr *ShiftAmount;
3533 SMLoc E = Parser.getTok().getLoc();
3534 if (getParser().ParseExpression(ShiftAmount)) {
3535 Error(E, "malformed rotate expression");
3536 return MatchOperand_ParseFail;
3537 }
3538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3539 if (!CE) {
3540 Error(E, "rotate amount must be an immediate");
3541 return MatchOperand_ParseFail;
3542 }
3543
3544 int64_t Val = CE->getValue();
3545 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3546 // normally, zero is represented in asm by omitting the rotate operand
3547 // entirely.
3548 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3549 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3550 return MatchOperand_ParseFail;
3551 }
3552
3553 E = Parser.getTok().getLoc();
3554 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3555
3556 return MatchOperand_Success;
3557}
3558
Jim Grosbach864b6092011-07-28 21:34:26 +00003559ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3560parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3561 SMLoc S = Parser.getTok().getLoc();
3562 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003563 if (Parser.getTok().isNot(AsmToken::Hash) &&
3564 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003565 Error(Parser.getTok().getLoc(), "'#' expected");
3566 return MatchOperand_ParseFail;
3567 }
3568 Parser.Lex(); // Eat hash token.
3569
3570 const MCExpr *LSBExpr;
3571 SMLoc E = Parser.getTok().getLoc();
3572 if (getParser().ParseExpression(LSBExpr)) {
3573 Error(E, "malformed immediate expression");
3574 return MatchOperand_ParseFail;
3575 }
3576 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3577 if (!CE) {
3578 Error(E, "'lsb' operand must be an immediate");
3579 return MatchOperand_ParseFail;
3580 }
3581
3582 int64_t LSB = CE->getValue();
3583 // The LSB must be in the range [0,31]
3584 if (LSB < 0 || LSB > 31) {
3585 Error(E, "'lsb' operand must be in the range [0,31]");
3586 return MatchOperand_ParseFail;
3587 }
3588 E = Parser.getTok().getLoc();
3589
3590 // Expect another immediate operand.
3591 if (Parser.getTok().isNot(AsmToken::Comma)) {
3592 Error(Parser.getTok().getLoc(), "too few operands");
3593 return MatchOperand_ParseFail;
3594 }
3595 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003596 if (Parser.getTok().isNot(AsmToken::Hash) &&
3597 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003598 Error(Parser.getTok().getLoc(), "'#' expected");
3599 return MatchOperand_ParseFail;
3600 }
3601 Parser.Lex(); // Eat hash token.
3602
3603 const MCExpr *WidthExpr;
3604 if (getParser().ParseExpression(WidthExpr)) {
3605 Error(E, "malformed immediate expression");
3606 return MatchOperand_ParseFail;
3607 }
3608 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3609 if (!CE) {
3610 Error(E, "'width' operand must be an immediate");
3611 return MatchOperand_ParseFail;
3612 }
3613
3614 int64_t Width = CE->getValue();
3615 // The LSB must be in the range [1,32-lsb]
3616 if (Width < 1 || Width > 32 - LSB) {
3617 Error(E, "'width' operand must be in the range [1,32-lsb]");
3618 return MatchOperand_ParseFail;
3619 }
3620 E = Parser.getTok().getLoc();
3621
3622 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3623
3624 return MatchOperand_Success;
3625}
3626
Jim Grosbachd3595712011-08-03 23:50:40 +00003627ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3628parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3629 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003630 // postidx_reg := '+' register {, shift}
3631 // | '-' register {, shift}
3632 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003633
3634 // This method must return MatchOperand_NoMatch without consuming any tokens
3635 // in the case where there is no match, as other alternatives take other
3636 // parse methods.
3637 AsmToken Tok = Parser.getTok();
3638 SMLoc S = Tok.getLoc();
3639 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003640 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003641 int Reg = -1;
3642 if (Tok.is(AsmToken::Plus)) {
3643 Parser.Lex(); // Eat the '+' token.
3644 haveEaten = true;
3645 } else if (Tok.is(AsmToken::Minus)) {
3646 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003647 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003648 haveEaten = true;
3649 }
3650 if (Parser.getTok().is(AsmToken::Identifier))
3651 Reg = tryParseRegister();
3652 if (Reg == -1) {
3653 if (!haveEaten)
3654 return MatchOperand_NoMatch;
3655 Error(Parser.getTok().getLoc(), "register expected");
3656 return MatchOperand_ParseFail;
3657 }
3658 SMLoc E = Parser.getTok().getLoc();
3659
Jim Grosbachc320c852011-08-05 21:28:30 +00003660 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3661 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003662 if (Parser.getTok().is(AsmToken::Comma)) {
3663 Parser.Lex(); // Eat the ','.
3664 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3665 return MatchOperand_ParseFail;
3666 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003667
3668 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3669 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003670
3671 return MatchOperand_Success;
3672}
3673
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003674ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3675parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3676 // Check for a post-index addressing register operand. Specifically:
3677 // am3offset := '+' register
3678 // | '-' register
3679 // | register
3680 // | # imm
3681 // | # + imm
3682 // | # - imm
3683
3684 // This method must return MatchOperand_NoMatch without consuming any tokens
3685 // in the case where there is no match, as other alternatives take other
3686 // parse methods.
3687 AsmToken Tok = Parser.getTok();
3688 SMLoc S = Tok.getLoc();
3689
3690 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003691 if (Parser.getTok().is(AsmToken::Hash) ||
3692 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003693 Parser.Lex(); // Eat the '#'.
3694 // Explicitly look for a '-', as we need to encode negative zero
3695 // differently.
3696 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3697 const MCExpr *Offset;
3698 if (getParser().ParseExpression(Offset))
3699 return MatchOperand_ParseFail;
3700 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3701 if (!CE) {
3702 Error(S, "constant expression expected");
3703 return MatchOperand_ParseFail;
3704 }
3705 SMLoc E = Tok.getLoc();
3706 // Negative zero is encoded as the flag value INT32_MIN.
3707 int32_t Val = CE->getValue();
3708 if (isNegative && Val == 0)
3709 Val = INT32_MIN;
3710
3711 Operands.push_back(
3712 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3713
3714 return MatchOperand_Success;
3715 }
3716
3717
3718 bool haveEaten = false;
3719 bool isAdd = true;
3720 int Reg = -1;
3721 if (Tok.is(AsmToken::Plus)) {
3722 Parser.Lex(); // Eat the '+' token.
3723 haveEaten = true;
3724 } else if (Tok.is(AsmToken::Minus)) {
3725 Parser.Lex(); // Eat the '-' token.
3726 isAdd = false;
3727 haveEaten = true;
3728 }
3729 if (Parser.getTok().is(AsmToken::Identifier))
3730 Reg = tryParseRegister();
3731 if (Reg == -1) {
3732 if (!haveEaten)
3733 return MatchOperand_NoMatch;
3734 Error(Parser.getTok().getLoc(), "register expected");
3735 return MatchOperand_ParseFail;
3736 }
3737 SMLoc E = Parser.getTok().getLoc();
3738
3739 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3740 0, S, E));
3741
3742 return MatchOperand_Success;
3743}
3744
Jim Grosbach7db8d692011-09-08 22:07:06 +00003745/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3746/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3747/// when they refer multiple MIOperands inside a single one.
3748bool ARMAsmParser::
3749cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3750 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3751 // Rt, Rt2
3752 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3753 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3754 // Create a writeback register dummy placeholder.
3755 Inst.addOperand(MCOperand::CreateReg(0));
3756 // addr
3757 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3758 // pred
3759 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3760 return true;
3761}
3762
3763/// cvtT2StrdPre - Convert parsed operands to MCInst.
3764/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3765/// when they refer multiple MIOperands inside a single one.
3766bool ARMAsmParser::
3767cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3768 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3769 // Create a writeback register dummy placeholder.
3770 Inst.addOperand(MCOperand::CreateReg(0));
3771 // Rt, Rt2
3772 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3773 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3774 // addr
3775 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3776 // pred
3777 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3778 return true;
3779}
3780
Jim Grosbachc086f682011-09-08 00:39:19 +00003781/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3782/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3783/// when they refer multiple MIOperands inside a single one.
3784bool ARMAsmParser::
3785cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3786 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3787 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3788
3789 // Create a writeback register dummy placeholder.
3790 Inst.addOperand(MCOperand::CreateImm(0));
3791
3792 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3793 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3794 return true;
3795}
3796
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003797/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3798/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3799/// when they refer multiple MIOperands inside a single one.
3800bool ARMAsmParser::
3801cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3802 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3803 // Create a writeback register dummy placeholder.
3804 Inst.addOperand(MCOperand::CreateImm(0));
3805 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3806 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3807 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3808 return true;
3809}
3810
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003811/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003812/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3813/// when they refer multiple MIOperands inside a single one.
3814bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003815cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003816 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3817 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3818
3819 // Create a writeback register dummy placeholder.
3820 Inst.addOperand(MCOperand::CreateImm(0));
3821
Jim Grosbachd3595712011-08-03 23:50:40 +00003822 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003823 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3824 return true;
3825}
3826
Owen Anderson16d33f32011-08-26 20:43:14 +00003827/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3828/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3829/// when they refer multiple MIOperands inside a single one.
3830bool ARMAsmParser::
3831cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3832 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3833 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3834
3835 // Create a writeback register dummy placeholder.
3836 Inst.addOperand(MCOperand::CreateImm(0));
3837
3838 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3839 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3840 return true;
3841}
3842
3843
Jim Grosbachd564bf32011-08-11 19:22:40 +00003844/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3845/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3846/// when they refer multiple MIOperands inside a single one.
3847bool ARMAsmParser::
3848cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3849 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3850 // Create a writeback register dummy placeholder.
3851 Inst.addOperand(MCOperand::CreateImm(0));
3852 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3853 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3854 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3855 return true;
3856}
3857
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003858/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003859/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3860/// when they refer multiple MIOperands inside a single one.
3861bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003862cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003863 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3864 // Create a writeback register dummy placeholder.
3865 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003866 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3867 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3868 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003869 return true;
3870}
3871
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003872/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3873/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3874/// when they refer multiple MIOperands inside a single one.
3875bool ARMAsmParser::
3876cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3877 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3878 // Create a writeback register dummy placeholder.
3879 Inst.addOperand(MCOperand::CreateImm(0));
3880 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3881 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3882 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3883 return true;
3884}
3885
Jim Grosbachd3595712011-08-03 23:50:40 +00003886/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3887/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3888/// when they refer multiple MIOperands inside a single one.
3889bool ARMAsmParser::
3890cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3891 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3892 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003893 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003894 // Create a writeback register dummy placeholder.
3895 Inst.addOperand(MCOperand::CreateImm(0));
3896 // addr
3897 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3898 // offset
3899 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3900 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003901 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3902 return true;
3903}
3904
Jim Grosbachd3595712011-08-03 23:50:40 +00003905/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003906/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3907/// when they refer multiple MIOperands inside a single one.
3908bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003909cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3910 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3911 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003912 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003913 // Create a writeback register dummy placeholder.
3914 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003915 // addr
3916 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3917 // offset
3918 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3919 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003920 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3921 return true;
3922}
3923
Jim Grosbachd3595712011-08-03 23:50:40 +00003924/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003925/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3926/// when they refer multiple MIOperands inside a single one.
3927bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003928cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3929 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003930 // Create a writeback register dummy placeholder.
3931 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003932 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003933 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003934 // addr
3935 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3936 // offset
3937 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3938 // pred
3939 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3940 return true;
3941}
3942
3943/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3944/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3945/// when they refer multiple MIOperands inside a single one.
3946bool ARMAsmParser::
3947cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3948 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3949 // Create a writeback register dummy placeholder.
3950 Inst.addOperand(MCOperand::CreateImm(0));
3951 // Rt
3952 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3953 // addr
3954 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3955 // offset
3956 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3957 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003958 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3959 return true;
3960}
3961
Jim Grosbach5b96b802011-08-10 20:29:19 +00003962/// cvtLdrdPre - Convert parsed operands to MCInst.
3963/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3964/// when they refer multiple MIOperands inside a single one.
3965bool ARMAsmParser::
3966cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3967 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3968 // Rt, Rt2
3969 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3970 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3971 // Create a writeback register dummy placeholder.
3972 Inst.addOperand(MCOperand::CreateImm(0));
3973 // addr
3974 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3975 // pred
3976 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3977 return true;
3978}
3979
Jim Grosbacheb09f492011-08-11 20:28:23 +00003980/// cvtStrdPre - Convert parsed operands to MCInst.
3981/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3982/// when they refer multiple MIOperands inside a single one.
3983bool ARMAsmParser::
3984cvtStrdPre(MCInst &Inst, unsigned Opcode,
3985 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3986 // Create a writeback register dummy placeholder.
3987 Inst.addOperand(MCOperand::CreateImm(0));
3988 // Rt, Rt2
3989 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3990 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3991 // addr
3992 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3993 // pred
3994 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3995 return true;
3996}
3997
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003998/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3999/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4000/// when they refer multiple MIOperands inside a single one.
4001bool ARMAsmParser::
4002cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
4003 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4004 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4005 // Create a writeback register dummy placeholder.
4006 Inst.addOperand(MCOperand::CreateImm(0));
4007 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4008 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4009 return true;
4010}
4011
Jim Grosbach8e048492011-08-19 22:07:46 +00004012/// cvtThumbMultiple- Convert parsed operands to MCInst.
4013/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4014/// when they refer multiple MIOperands inside a single one.
4015bool ARMAsmParser::
4016cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4017 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4018 // The second source operand must be the same register as the destination
4019 // operand.
4020 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00004021 (((ARMOperand*)Operands[3])->getReg() !=
4022 ((ARMOperand*)Operands[5])->getReg()) &&
4023 (((ARMOperand*)Operands[3])->getReg() !=
4024 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00004025 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00004026 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00004027 return false;
4028 }
4029 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4030 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00004031 // If we have a three-operand form, make sure to set Rn to be the operand
4032 // that isn't the same as Rd.
4033 unsigned RegOp = 4;
4034 if (Operands.size() == 6 &&
4035 ((ARMOperand*)Operands[4])->getReg() ==
4036 ((ARMOperand*)Operands[3])->getReg())
4037 RegOp = 5;
4038 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4039 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00004040 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4041
4042 return true;
4043}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00004044
Jim Grosbach3ea06572011-10-24 22:16:58 +00004045bool ARMAsmParser::
4046cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4047 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4048 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00004049 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00004050 // Create a writeback register dummy placeholder.
4051 Inst.addOperand(MCOperand::CreateImm(0));
4052 // Vn
4053 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4054 // pred
4055 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4056 return true;
4057}
4058
4059bool ARMAsmParser::
4060cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4061 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4062 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00004063 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00004064 // Create a writeback register dummy placeholder.
4065 Inst.addOperand(MCOperand::CreateImm(0));
4066 // Vn
4067 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4068 // Vm
4069 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4070 // pred
4071 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4072 return true;
4073}
4074
Jim Grosbach05df4602011-10-31 21:50:31 +00004075bool ARMAsmParser::
4076cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4077 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4078 // Create a writeback register dummy placeholder.
4079 Inst.addOperand(MCOperand::CreateImm(0));
4080 // Vn
4081 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4082 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00004083 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00004084 // pred
4085 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4086 return true;
4087}
4088
4089bool ARMAsmParser::
4090cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4091 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4092 // Create a writeback register dummy placeholder.
4093 Inst.addOperand(MCOperand::CreateImm(0));
4094 // Vn
4095 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4096 // Vm
4097 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4098 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00004099 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00004100 // pred
4101 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4102 return true;
4103}
4104
Bill Wendlinge18980a2010-11-06 22:36:58 +00004105/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004106/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00004107bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00004108parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004109 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00004110 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00004111 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004112 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004113 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004114
Sean Callanan936b0d32010-01-19 21:44:56 +00004115 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004116 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00004117 if (BaseRegNum == -1)
4118 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004119
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004120 // The next token must either be a comma or a closing bracket.
4121 const AsmToken &Tok = Parser.getTok();
4122 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00004123 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004124
Jim Grosbachd3595712011-08-03 23:50:40 +00004125 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004126 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004127 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004128
Jim Grosbachd3595712011-08-03 23:50:40 +00004129 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004130 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00004131
Jim Grosbach40700e02011-09-19 18:42:21 +00004132 // If there's a pre-indexing writeback marker, '!', just add it as a token
4133 // operand. It's rather odd, but syntactically valid.
4134 if (Parser.getTok().is(AsmToken::Exclaim)) {
4135 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4136 Parser.Lex(); // Eat the '!'.
4137 }
4138
Jim Grosbachd3595712011-08-03 23:50:40 +00004139 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004140 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004141
Jim Grosbachd3595712011-08-03 23:50:40 +00004142 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4143 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004144
Jim Grosbacha95ec992011-10-11 17:29:55 +00004145 // If we have a ':', it's an alignment specifier.
4146 if (Parser.getTok().is(AsmToken::Colon)) {
4147 Parser.Lex(); // Eat the ':'.
4148 E = Parser.getTok().getLoc();
4149
4150 const MCExpr *Expr;
4151 if (getParser().ParseExpression(Expr))
4152 return true;
4153
4154 // The expression has to be a constant. Memory references with relocations
4155 // don't come through here, as they use the <label> forms of the relevant
4156 // instructions.
4157 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4158 if (!CE)
4159 return Error (E, "constant expression expected");
4160
4161 unsigned Align = 0;
4162 switch (CE->getValue()) {
4163 default:
Jim Grosbachcef98cd2011-12-19 18:31:43 +00004164 return Error(E,
4165 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4166 case 16: Align = 2; break;
4167 case 32: Align = 4; break;
Jim Grosbacha95ec992011-10-11 17:29:55 +00004168 case 64: Align = 8; break;
4169 case 128: Align = 16; break;
4170 case 256: Align = 32; break;
4171 }
4172
4173 // Now we should have the closing ']'
4174 E = Parser.getTok().getLoc();
4175 if (Parser.getTok().isNot(AsmToken::RBrac))
4176 return Error(E, "']' expected");
4177 Parser.Lex(); // Eat right bracket token.
4178
4179 // Don't worry about range checking the value here. That's handled by
4180 // the is*() predicates.
4181 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4182 ARM_AM::no_shift, 0, Align,
4183 false, S, E));
4184
4185 // If there's a pre-indexing writeback marker, '!', just add it as a token
4186 // operand.
4187 if (Parser.getTok().is(AsmToken::Exclaim)) {
4188 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4189 Parser.Lex(); // Eat the '!'.
4190 }
4191
4192 return false;
4193 }
4194
4195 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00004196 // offset. Be friendly and also accept a plain integer (without a leading
4197 // hash) for gas compatibility.
4198 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004199 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00004200 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004201 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00004202 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00004203 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004204
Owen Anderson967674d2011-08-29 19:36:44 +00004205 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00004206 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004207 if (getParser().ParseExpression(Offset))
4208 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004209
4210 // The expression has to be a constant. Memory references with relocations
4211 // don't come through here, as they use the <label> forms of the relevant
4212 // instructions.
4213 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4214 if (!CE)
4215 return Error (E, "constant expression expected");
4216
Owen Anderson967674d2011-08-29 19:36:44 +00004217 // If the constant was #-0, represent it as INT32_MIN.
4218 int32_t Val = CE->getValue();
4219 if (isNegative && Val == 0)
4220 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4221
Jim Grosbachd3595712011-08-03 23:50:40 +00004222 // 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, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004231 ARM_AM::no_shift, 0, 0,
4232 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004233
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;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004242 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004243
4244 // The register offset is optionally preceded by a '+' or '-'
4245 bool isNegative = false;
4246 if (Parser.getTok().is(AsmToken::Minus)) {
4247 isNegative = true;
4248 Parser.Lex(); // Eat the '-'.
4249 } else if (Parser.getTok().is(AsmToken::Plus)) {
4250 // Nothing to do.
4251 Parser.Lex(); // Eat the '+'.
4252 }
4253
4254 E = Parser.getTok().getLoc();
4255 int OffsetRegNum = tryParseRegister();
4256 if (OffsetRegNum == -1)
4257 return Error(E, "register expected");
4258
4259 // If there's a shift operator, handle it.
4260 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004261 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004262 if (Parser.getTok().is(AsmToken::Comma)) {
4263 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004264 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004265 return true;
4266 }
4267
4268 // Now we should have the closing ']'
4269 E = Parser.getTok().getLoc();
4270 if (Parser.getTok().isNot(AsmToken::RBrac))
4271 return Error(E, "']' expected");
4272 Parser.Lex(); // Eat right bracket token.
4273
4274 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004275 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004276 S, E));
4277
Jim Grosbachc320c852011-08-05 21:28:30 +00004278 // If there's a pre-indexing writeback marker, '!', just add it as a token
4279 // operand.
4280 if (Parser.getTok().is(AsmToken::Exclaim)) {
4281 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4282 Parser.Lex(); // Eat the '!'.
4283 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004284
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004285 return false;
4286}
4287
Jim Grosbachd3595712011-08-03 23:50:40 +00004288/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004289/// ( lsl | lsr | asr | ror ) , # shift_amount
4290/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004291/// return true if it parses a shift otherwise it returns false.
4292bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4293 unsigned &Amount) {
4294 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004295 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004296 if (Tok.isNot(AsmToken::Identifier))
4297 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004298 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004299 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4300 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004301 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004302 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004303 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004304 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004305 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004306 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004307 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004308 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004309 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004310 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004311 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004312 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004313
Jim Grosbachd3595712011-08-03 23:50:40 +00004314 // rrx stands alone.
4315 Amount = 0;
4316 if (St != ARM_AM::rrx) {
4317 Loc = Parser.getTok().getLoc();
4318 // A '#' and a shift amount.
4319 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004320 if (HashTok.isNot(AsmToken::Hash) &&
4321 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004322 return Error(HashTok.getLoc(), "'#' expected");
4323 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004324
Jim Grosbachd3595712011-08-03 23:50:40 +00004325 const MCExpr *Expr;
4326 if (getParser().ParseExpression(Expr))
4327 return true;
4328 // Range check the immediate.
4329 // lsl, ror: 0 <= imm <= 31
4330 // lsr, asr: 0 <= imm <= 32
4331 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4332 if (!CE)
4333 return Error(Loc, "shift amount must be an immediate");
4334 int64_t Imm = CE->getValue();
4335 if (Imm < 0 ||
4336 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4337 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4338 return Error(Loc, "immediate shift value out of range");
4339 Amount = Imm;
4340 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004341
4342 return false;
4343}
4344
Jim Grosbache7fbce72011-10-03 23:38:36 +00004345/// parseFPImm - A floating point immediate expression operand.
4346ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4347parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004348 // Anything that can accept a floating point constant as an operand
4349 // needs to go through here, as the regular ParseExpression is
4350 // integer only.
4351 //
4352 // This routine still creates a generic Immediate operand, containing
4353 // a bitcast of the 64-bit floating point value. The various operands
4354 // that accept floats can check whether the value is valid for them
4355 // via the standard is*() predicates.
4356
Jim Grosbache7fbce72011-10-03 23:38:36 +00004357 SMLoc S = Parser.getTok().getLoc();
4358
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004359 if (Parser.getTok().isNot(AsmToken::Hash) &&
4360 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004361 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004362
4363 // Disambiguate the VMOV forms that can accept an FP immediate.
4364 // vmov.f32 <sreg>, #imm
4365 // vmov.f64 <dreg>, #imm
4366 // vmov.f32 <dreg>, #imm @ vector f32x2
4367 // vmov.f32 <qreg>, #imm @ vector f32x4
4368 //
4369 // There are also the NEON VMOV instructions which expect an
4370 // integer constant. Make sure we don't try to parse an FPImm
4371 // for these:
4372 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4373 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4374 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4375 TyOp->getToken() != ".f64"))
4376 return MatchOperand_NoMatch;
4377
Jim Grosbache7fbce72011-10-03 23:38:36 +00004378 Parser.Lex(); // Eat the '#'.
4379
4380 // Handle negation, as that still comes through as a separate token.
4381 bool isNegative = false;
4382 if (Parser.getTok().is(AsmToken::Minus)) {
4383 isNegative = true;
4384 Parser.Lex();
4385 }
4386 const AsmToken &Tok = Parser.getTok();
Jim Grosbach235c8d22012-01-19 02:47:30 +00004387 SMLoc Loc = Tok.getLoc();
Jim Grosbache7fbce72011-10-03 23:38:36 +00004388 if (Tok.is(AsmToken::Real)) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004389 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbache7fbce72011-10-03 23:38:36 +00004390 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4391 // If we had a '-' in front, toggle the sign bit.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004392 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbache7fbce72011-10-03 23:38:36 +00004393 Parser.Lex(); // Eat the token.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004394 Operands.push_back(ARMOperand::CreateImm(
4395 MCConstantExpr::Create(IntVal, getContext()),
4396 S, Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004397 return MatchOperand_Success;
4398 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004399 // Also handle plain integers. Instructions which allow floating point
4400 // immediates also allow a raw encoded 8-bit value.
Jim Grosbache7fbce72011-10-03 23:38:36 +00004401 if (Tok.is(AsmToken::Integer)) {
4402 int64_t Val = Tok.getIntVal();
4403 Parser.Lex(); // Eat the token.
4404 if (Val > 255 || Val < 0) {
Jim Grosbach235c8d22012-01-19 02:47:30 +00004405 Error(Loc, "encoded floating point value out of range");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004406 return MatchOperand_ParseFail;
4407 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004408 double RealVal = ARM_AM::getFPImmFloat(Val);
4409 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4410 Operands.push_back(ARMOperand::CreateImm(
4411 MCConstantExpr::Create(Val, getContext()), S,
4412 Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004413 return MatchOperand_Success;
4414 }
4415
Jim Grosbach235c8d22012-01-19 02:47:30 +00004416 Error(Loc, "invalid floating point immediate");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004417 return MatchOperand_ParseFail;
4418}
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004419
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004420/// Parse a arm instruction operand. For now this parses the operand regardless
4421/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004422bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004423 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004424 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004425
4426 // Check if the current operand has a custom associated parser, if so, try to
4427 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004428 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4429 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004430 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004431 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4432 // there was a match, but an error occurred, in which case, just return that
4433 // the operand parsing failed.
4434 if (ResTy == MatchOperand_ParseFail)
4435 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004436
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004437 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004438 default:
4439 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004440 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004441 case AsmToken::Identifier: {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004442 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004443 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004444 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004445 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004446 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004447 else if (Res == -1) // irrecoverable error
4448 return true;
Jim Grosbach4eda1452011-12-20 22:26:38 +00004449 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachd28888d2012-03-15 21:34:14 +00004450 if (Mnemonic == "vmrs" &&
4451 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004452 S = Parser.getTok().getLoc();
4453 Parser.Lex();
Jim Grosbachd28888d2012-03-15 21:34:14 +00004454 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004455 return false;
4456 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004457
4458 // Fall though for the Identifier case that is not a register or a
4459 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004460 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004461 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004462 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004463 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004464 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004465 // This was not a register so parse other operands that start with an
4466 // identifier (like labels) as expressions and create them as immediates.
4467 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004468 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004469 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004470 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004471 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004472 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4473 return false;
4474 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004475 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004476 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004477 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004478 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004479 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004480 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004481 // #42 -> immediate.
4482 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004483 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004484 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004485 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004486 const MCExpr *ImmVal;
4487 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004488 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004489 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004490 if (CE) {
4491 int32_t Val = CE->getValue();
4492 if (isNegative && Val == 0)
4493 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004494 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004495 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004496 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4497 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004498 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004499 case AsmToken::Colon: {
4500 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004501 // FIXME: Check it's an expression prefix,
4502 // e.g. (FOO - :lower16:BAR) isn't legal.
4503 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004504 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004505 return true;
4506
Evan Cheng965b3c72011-01-13 07:58:56 +00004507 const MCExpr *SubExprVal;
4508 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004509 return true;
4510
Evan Cheng965b3c72011-01-13 07:58:56 +00004511 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4512 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004513 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004514 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004515 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004516 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004517 }
4518}
4519
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004520// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004521// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004522bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004523 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004524
4525 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004526 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004527 Parser.Lex(); // Eat ':'
4528
4529 if (getLexer().isNot(AsmToken::Identifier)) {
4530 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4531 return true;
4532 }
4533
4534 StringRef IDVal = Parser.getTok().getIdentifier();
4535 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004536 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004537 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004538 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004539 } else {
4540 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4541 return true;
4542 }
4543 Parser.Lex();
4544
4545 if (getLexer().isNot(AsmToken::Colon)) {
4546 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4547 return true;
4548 }
4549 Parser.Lex(); // Eat the last ':'
4550 return false;
4551}
4552
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004553/// \brief Given a mnemonic, split out possible predication code and carry
4554/// setting letters to form a canonical mnemonic and flags.
4555//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004556// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004557// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004558StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004559 unsigned &PredicationCode,
4560 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004561 unsigned &ProcessorIMod,
4562 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004563 PredicationCode = ARMCC::AL;
4564 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004565 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004566
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004567 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004568 //
4569 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004570 if ((Mnemonic == "movs" && isThumb()) ||
4571 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4572 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4573 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4574 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4575 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4576 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004577 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4578 Mnemonic == "fmuls")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004579 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004580
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004581 // First, split out any predication code. Ignore mnemonics we know aren't
4582 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004583 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004584 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004585 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004586 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004587 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4588 .Case("eq", ARMCC::EQ)
4589 .Case("ne", ARMCC::NE)
4590 .Case("hs", ARMCC::HS)
4591 .Case("cs", ARMCC::HS)
4592 .Case("lo", ARMCC::LO)
4593 .Case("cc", ARMCC::LO)
4594 .Case("mi", ARMCC::MI)
4595 .Case("pl", ARMCC::PL)
4596 .Case("vs", ARMCC::VS)
4597 .Case("vc", ARMCC::VC)
4598 .Case("hi", ARMCC::HI)
4599 .Case("ls", ARMCC::LS)
4600 .Case("ge", ARMCC::GE)
4601 .Case("lt", ARMCC::LT)
4602 .Case("gt", ARMCC::GT)
4603 .Case("le", ARMCC::LE)
4604 .Case("al", ARMCC::AL)
4605 .Default(~0U);
4606 if (CC != ~0U) {
4607 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4608 PredicationCode = CC;
4609 }
Bill Wendling193961b2010-10-29 23:50:21 +00004610 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004611
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004612 // Next, determine if we have a carry setting bit. We explicitly ignore all
4613 // the instructions we know end in 's'.
4614 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004615 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004616 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4617 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4618 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004619 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004620 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach92a939a2011-12-19 19:02:41 +00004621 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbachd74560b2012-03-15 20:48:18 +00004622 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004623 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004624 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4625 CarrySetting = true;
4626 }
4627
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004628 // The "cps" instruction can have a interrupt mode operand which is glued into
4629 // the mnemonic. Check if this is the case, split it and parse the imod op
4630 if (Mnemonic.startswith("cps")) {
4631 // Split out any imod code.
4632 unsigned IMod =
4633 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4634 .Case("ie", ARM_PROC::IE)
4635 .Case("id", ARM_PROC::ID)
4636 .Default(~0U);
4637 if (IMod != ~0U) {
4638 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4639 ProcessorIMod = IMod;
4640 }
4641 }
4642
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004643 // The "it" instruction has the condition mask on the end of the mnemonic.
4644 if (Mnemonic.startswith("it")) {
4645 ITMask = Mnemonic.slice(2, Mnemonic.size());
4646 Mnemonic = Mnemonic.slice(0, 2);
4647 }
4648
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004649 return Mnemonic;
4650}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004651
4652/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4653/// inclusion of carry set or predication code operands.
4654//
4655// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004656void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004657getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004658 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004659 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4660 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004661 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004662 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004663 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004664 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004665 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004666 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004667 Mnemonic == "mla" || Mnemonic == "smlal" ||
4668 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004669 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004670 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004671 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004672
Daniel Dunbar09264122011-01-11 19:06:29 +00004673 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4674 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4675 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4676 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004677 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4678 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004679 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004680 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4681 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4682 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004683 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4684 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004685 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004686 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004687 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004688 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004689
Jim Grosbach6c45b752011-09-16 16:39:25 +00004690 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004691 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004692 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004693 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004694 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004695}
4696
Jim Grosbach7283da92011-08-16 21:12:37 +00004697bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4698 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004699 // FIXME: This is all horribly hacky. We really need a better way to deal
4700 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004701
4702 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4703 // another does not. Specifically, the MOVW instruction does not. So we
4704 // special case it here and remove the defaulted (non-setting) cc_out
4705 // operand if that's the instruction we're trying to match.
4706 //
4707 // We do this as post-processing of the explicit operands rather than just
4708 // conditionally adding the cc_out in the first place because we need
4709 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004710 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004711 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4712 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4713 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4714 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004715
4716 // Register-register 'add' for thumb does not have a cc_out operand
4717 // when there are only two register operands.
4718 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4719 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4720 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4721 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4722 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004723 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004724 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4725 // have to check the immediate range here since Thumb2 has a variant
4726 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004727 if (((isThumb() && Mnemonic == "add") ||
4728 (isThumbTwo() && Mnemonic == "sub")) &&
4729 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004730 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4731 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4732 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004733 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4734 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4735 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004736 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004737 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4738 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004739 // selecting via the generic "add" mnemonic, so to know that we
4740 // should remove the cc_out operand, we have to explicitly check that
4741 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004742 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4743 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004744 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4745 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4746 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4747 // Nest conditions rather than one big 'if' statement for readability.
4748 //
4749 // If either register is a high reg, it's either one of the SP
4750 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004751 // check against T3. If the second register is the PC, this is an
4752 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004753 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4754 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004755 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004756 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4757 return false;
4758 // If both registers are low, we're in an IT block, and the immediate is
4759 // in range, we should use encoding T1 instead, which has a cc_out.
4760 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004761 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004762 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4763 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4764 return false;
4765
4766 // Otherwise, we use encoding T4, which does not have a cc_out
4767 // operand.
4768 return true;
4769 }
4770
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004771 // The thumb2 multiply instruction doesn't have a CCOut register, so
4772 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4773 // use the 16-bit encoding or not.
4774 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4775 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4776 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4777 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4778 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4779 // If the registers aren't low regs, the destination reg isn't the
4780 // same as one of the source regs, or the cc_out operand is zero
4781 // outside of an IT block, we have to use the 32-bit encoding, so
4782 // remove the cc_out operand.
4783 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4784 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004785 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004786 !inITBlock() ||
4787 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4788 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4789 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4790 static_cast<ARMOperand*>(Operands[4])->getReg())))
4791 return true;
4792
Jim Grosbachefa7e952011-11-15 19:55:16 +00004793 // Also check the 'mul' syntax variant that doesn't specify an explicit
4794 // destination register.
4795 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4796 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4797 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4798 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4799 // If the registers aren't low regs or the cc_out operand is zero
4800 // outside of an IT block, we have to use the 32-bit encoding, so
4801 // remove the cc_out operand.
4802 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4803 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4804 !inITBlock()))
4805 return true;
4806
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004807
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004808
Jim Grosbach4b701af2011-08-24 21:42:27 +00004809 // Register-register 'add/sub' for thumb does not have a cc_out operand
4810 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4811 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4812 // right, this will result in better diagnostics (which operand is off)
4813 // anyway.
4814 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4815 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004816 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4817 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4818 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4819 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004820
Jim Grosbach7283da92011-08-16 21:12:37 +00004821 return false;
4822}
4823
Jim Grosbach12952fe2011-11-11 23:08:10 +00004824static bool isDataTypeToken(StringRef Tok) {
4825 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4826 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4827 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4828 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4829 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4830 Tok == ".f" || Tok == ".d";
4831}
4832
4833// FIXME: This bit should probably be handled via an explicit match class
4834// in the .td files that matches the suffix instead of having it be
4835// a literal string token the way it is now.
4836static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4837 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4838}
4839
Jim Grosbach8be2f652011-12-09 23:34:09 +00004840static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004841/// Parse an arm instruction mnemonic followed by its operands.
4842bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4843 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004844 // Apply mnemonic aliases before doing anything else, as the destination
4845 // mnemnonic may include suffices and we want to handle them normally.
4846 // The generic tblgen'erated code does this later, at the start of
4847 // MatchInstructionImpl(), but that's too late for aliases that include
4848 // any sort of suffix.
4849 unsigned AvailableFeatures = getAvailableFeatures();
4850 applyMnemonicAliases(Name, AvailableFeatures);
4851
Jim Grosbachab5830e2011-12-14 02:16:11 +00004852 // First check for the ARM-specific .req directive.
4853 if (Parser.getTok().is(AsmToken::Identifier) &&
4854 Parser.getTok().getIdentifier() == ".req") {
4855 parseDirectiveReq(Name, NameLoc);
4856 // We always return 'error' for this, as we're done with this
4857 // statement and don't need to match the 'instruction."
4858 return true;
4859 }
4860
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004861 // Create the leading tokens for the mnemonic, split by '.' characters.
4862 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004863 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004864
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004865 // Split out the predication code and carry setting flag from the mnemonic.
4866 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004867 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004868 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004869 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004870 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004871 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004872
Jim Grosbach1c171b12011-08-25 17:23:55 +00004873 // In Thumb1, only the branch (B) instruction can be predicated.
4874 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4875 Parser.EatToEndOfStatement();
4876 return Error(NameLoc, "conditional execution not supported in Thumb1");
4877 }
4878
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004879 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4880
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004881 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4882 // is the mask as it will be for the IT encoding if the conditional
4883 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4884 // where the conditional bit0 is zero, the instruction post-processing
4885 // will adjust the mask accordingly.
4886 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004887 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4888 if (ITMask.size() > 3) {
4889 Parser.EatToEndOfStatement();
4890 return Error(Loc, "too many conditions on IT instruction");
4891 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004892 unsigned Mask = 8;
4893 for (unsigned i = ITMask.size(); i != 0; --i) {
4894 char pos = ITMask[i - 1];
4895 if (pos != 't' && pos != 'e') {
4896 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004897 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004898 }
4899 Mask >>= 1;
4900 if (ITMask[i - 1] == 't')
4901 Mask |= 8;
4902 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004903 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004904 }
4905
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004906 // FIXME: This is all a pretty gross hack. We should automatically handle
4907 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004908
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004909 // Next, add the CCOut and ConditionCode operands, if needed.
4910 //
4911 // For mnemonics which can ever incorporate a carry setting bit or predication
4912 // code, our matching model involves us always generating CCOut and
4913 // ConditionCode operands to match the mnemonic "as written" and then we let
4914 // the matcher deal with finding the right instruction or generating an
4915 // appropriate error.
4916 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004917 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004918
Jim Grosbach03a8a162011-07-14 22:04:21 +00004919 // If we had a carry-set on an instruction that can't do that, issue an
4920 // error.
4921 if (!CanAcceptCarrySet && CarrySetting) {
4922 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004923 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004924 "' can not set flags, but 's' suffix specified");
4925 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004926 // If we had a predication code on an instruction that can't do that, issue an
4927 // error.
4928 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4929 Parser.EatToEndOfStatement();
4930 return Error(NameLoc, "instruction '" + Mnemonic +
4931 "' is not predicable, but condition code specified");
4932 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004933
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004934 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004935 if (CanAcceptCarrySet) {
4936 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004937 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004938 Loc));
4939 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004940
4941 // Add the predication code operand, if necessary.
4942 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004943 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4944 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004945 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004946 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004947 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004948
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004949 // Add the processor imod operand, if necessary.
4950 if (ProcessorIMod) {
4951 Operands.push_back(ARMOperand::CreateImm(
4952 MCConstantExpr::Create(ProcessorIMod, getContext()),
4953 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004954 }
4955
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004956 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004957 while (Next != StringRef::npos) {
4958 Start = Next;
4959 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004960 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004961
Jim Grosbach12952fe2011-11-11 23:08:10 +00004962 // Some NEON instructions have an optional datatype suffix that is
4963 // completely ignored. Check for that.
4964 if (isDataTypeToken(ExtraToken) &&
4965 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4966 continue;
4967
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004968 if (ExtraToken != ".n") {
4969 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4970 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4971 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004972 }
4973
4974 // Read the remaining operands.
4975 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004976 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004977 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004978 Parser.EatToEndOfStatement();
4979 return true;
4980 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004981
4982 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004983 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004984
4985 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004986 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004987 Parser.EatToEndOfStatement();
4988 return true;
4989 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004990 }
4991 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004992
Chris Lattnera2a9d162010-09-11 16:18:25 +00004993 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004994 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004995 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004996 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004997 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004998
Chris Lattner91689c12010-09-08 05:10:46 +00004999 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005000
Jim Grosbach7283da92011-08-16 21:12:37 +00005001 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5002 // do and don't have a cc_out optional-def operand. With some spot-checks
5003 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005004 // parse and adjust accordingly before actually matching. We shouldn't ever
5005 // try to remove a cc_out operand that was explicitly set on the the
5006 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5007 // table driven matcher doesn't fit well with the ARM instruction set.
5008 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005009 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5010 Operands.erase(Operands.begin() + 1);
5011 delete Op;
5012 }
5013
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005014 // ARM mode 'blx' need special handling, as the register operand version
5015 // is predicable, but the label operand version is not. So, we can't rely
5016 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00005017 // a k_CondCode operand in the list. If we're trying to match the label
5018 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005019 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5020 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5021 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5022 Operands.erase(Operands.begin() + 1);
5023 delete Op;
5024 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00005025
5026 // The vector-compare-to-zero instructions have a literal token "#0" at
5027 // the end that comes to here as an immediate operand. Convert it to a
5028 // token to play nicely with the matcher.
5029 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5030 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5031 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5032 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5033 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5034 if (CE && CE->getValue() == 0) {
5035 Operands.erase(Operands.begin() + 5);
5036 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5037 delete Op;
5038 }
5039 }
Jim Grosbach46b66462011-10-03 22:30:24 +00005040 // VCMP{E} does the same thing, but with a different operand count.
5041 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5042 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5043 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5044 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5045 if (CE && CE->getValue() == 0) {
5046 Operands.erase(Operands.begin() + 4);
5047 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5048 delete Op;
5049 }
5050 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005051 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005052 // end. Convert it to a token here. Take care not to convert those
5053 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005054 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005055 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5056 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005057 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5058 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005060 if (CE && CE->getValue() == 0 &&
5061 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00005062 // The cc_out operand matches the IT block.
5063 ((inITBlock() != CarrySetting) &&
5064 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005065 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00005066 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005067 Operands.erase(Operands.begin() + 5);
5068 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5069 delete Op;
5070 }
5071 }
5072
Chris Lattnerf29c0b62010-01-14 22:21:20 +00005073 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00005074}
5075
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005076// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005077
5078// return 'true' if register list contains non-low GPR registers,
5079// 'false' otherwise. If Reg is in the register list or is HiReg, set
5080// 'containsReg' to true.
5081static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5082 unsigned HiReg, bool &containsReg) {
5083 containsReg = false;
5084 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5085 unsigned OpReg = Inst.getOperand(i).getReg();
5086 if (OpReg == Reg)
5087 containsReg = true;
5088 // Anything other than a low register isn't legal here.
5089 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5090 return true;
5091 }
5092 return false;
5093}
5094
Jim Grosbacha31f2232011-09-07 18:05:34 +00005095// Check if the specified regisgter is in the register list of the inst,
5096// starting at the indicated operand number.
5097static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5098 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5099 unsigned OpReg = Inst.getOperand(i).getReg();
5100 if (OpReg == Reg)
5101 return true;
5102 }
5103 return false;
5104}
5105
Jim Grosbached16ec42011-08-29 22:24:09 +00005106// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5107// the ARMInsts array) instead. Getting that here requires awkward
5108// API changes, though. Better way?
5109namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005110extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00005111}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005112static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005113 return ARMInsts[Opcode];
5114}
5115
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005116// FIXME: We would really like to be able to tablegen'erate this.
5117bool ARMAsmParser::
5118validateInstruction(MCInst &Inst,
5119 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005120 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00005121 SMLoc Loc = Operands[0]->getStartLoc();
5122 // Check the IT block state first.
Jim Grosbach82f76d12012-01-25 19:52:01 +00005123 // NOTE: BKPT instruction has the interesting property of being
5124 // allowed in IT blocks, but not being predicable. It just always
Owen Anderson44ae2da2011-09-13 17:59:19 +00005125 // executes.
Jim Grosbach82f76d12012-01-25 19:52:01 +00005126 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5127 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005128 unsigned bit = 1;
5129 if (ITState.FirstCond)
5130 ITState.FirstCond = false;
5131 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005132 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00005133 // The instruction must be predicable.
5134 if (!MCID.isPredicable())
5135 return Error(Loc, "instructions in IT block must be predicable");
5136 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5137 unsigned ITCond = bit ? ITState.Cond :
5138 ARMCC::getOppositeCondition(ITState.Cond);
5139 if (Cond != ITCond) {
5140 // Find the condition code Operand to get its SMLoc information.
5141 SMLoc CondLoc;
5142 for (unsigned i = 1; i < Operands.size(); ++i)
5143 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5144 CondLoc = Operands[i]->getStartLoc();
5145 return Error(CondLoc, "incorrect condition in IT block; got '" +
5146 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5147 "', but expected '" +
5148 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5149 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00005150 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005151 } else if (isThumbTwo() && MCID.isPredicable() &&
5152 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005153 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5154 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00005155 return Error(Loc, "predicated instructions must be in IT block");
5156
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005157 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00005158 case ARM::LDRD:
5159 case ARM::LDRD_PRE:
5160 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005161 case ARM::LDREXD: {
5162 // Rt2 must be Rt + 1.
5163 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5164 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5165 if (Rt2 != Rt + 1)
5166 return Error(Operands[3]->getStartLoc(),
5167 "destination operands must be sequential");
5168 return false;
5169 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00005170 case ARM::STRD: {
5171 // Rt2 must be Rt + 1.
5172 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5173 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5174 if (Rt2 != Rt + 1)
5175 return Error(Operands[3]->getStartLoc(),
5176 "source operands must be sequential");
5177 return false;
5178 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00005179 case ARM::STRD_PRE:
5180 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005181 case ARM::STREXD: {
5182 // Rt2 must be Rt + 1.
5183 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5184 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5185 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00005186 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005187 "source operands must be sequential");
5188 return false;
5189 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00005190 case ARM::SBFX:
5191 case ARM::UBFX: {
5192 // width must be in range [1, 32-lsb]
5193 unsigned lsb = Inst.getOperand(2).getImm();
5194 unsigned widthm1 = Inst.getOperand(3).getImm();
5195 if (widthm1 >= 32 - lsb)
5196 return Error(Operands[5]->getStartLoc(),
5197 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00005198 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00005199 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00005200 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00005201 // If we're parsing Thumb2, the .w variant is available and handles
5202 // most cases that are normally illegal for a Thumb1 LDM
5203 // instruction. We'll make the transformation in processInstruction()
5204 // if necessary.
5205 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00005206 // Thumb LDM instructions are writeback iff the base register is not
5207 // in the register list.
5208 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00005209 bool hasWritebackToken =
5210 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5211 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00005212 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005213 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005214 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5215 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005216 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00005217 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00005218 return Error(Operands[2]->getStartLoc(),
5219 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00005220 // If we should not have writeback, there must not be a '!'. This is
5221 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005222 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00005223 return Error(Operands[3]->getStartLoc(),
5224 "writeback operator '!' not allowed when base register "
5225 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005226
5227 break;
5228 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00005229 case ARM::t2LDMIA_UPD: {
5230 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5231 return Error(Operands[4]->getStartLoc(),
5232 "writeback operator '!' not allowed when base register "
5233 "in register list");
5234 break;
5235 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005236 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5237 // so only issue a diagnostic for thumb1. The instructions will be
5238 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005239 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005240 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005241 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5242 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005243 return Error(Operands[2]->getStartLoc(),
5244 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005245 break;
5246 }
5247 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005248 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005249 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5250 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005251 return Error(Operands[2]->getStartLoc(),
5252 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005253 break;
5254 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00005255 case ARM::tSTMIA_UPD: {
5256 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00005257 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00005258 return Error(Operands[4]->getStartLoc(),
5259 "registers must be in range r0-r7");
5260 break;
5261 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005262 }
5263
5264 return false;
5265}
5266
Jim Grosbach1a747242012-01-23 23:45:44 +00005267static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbacheb538222011-12-02 22:34:51 +00005268 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00005269 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005270 // VST1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005271 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5272 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5273 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5274 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5275 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5276 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5277 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5278 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5279 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005280
5281 // VST2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005282 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5283 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5284 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5285 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5286 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005287
Jim Grosbach1e946a42012-01-24 00:43:12 +00005288 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5289 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5290 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5291 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5292 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005293
Jim Grosbach1e946a42012-01-24 00:43:12 +00005294 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5295 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5296 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5297 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5298 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbach1a747242012-01-23 23:45:44 +00005299
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005300 // VST3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005301 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5302 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5303 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5304 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5305 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5306 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5307 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5308 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5309 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5310 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5311 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5312 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5313 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5314 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5315 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005316
Jim Grosbach1a747242012-01-23 23:45:44 +00005317 // VST3
Jim Grosbach1e946a42012-01-24 00:43:12 +00005318 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5319 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5320 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5321 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5322 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5323 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5324 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5325 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5326 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5327 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5328 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5329 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5330 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5331 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5332 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5333 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5334 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5335 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbachda70eac2012-01-24 00:58:13 +00005336
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005337 // VST4LN
5338 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5339 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5340 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5341 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5342 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5343 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5344 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5345 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5346 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5347 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5348 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5349 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5350 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5351 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5352 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5353
Jim Grosbachda70eac2012-01-24 00:58:13 +00005354 // VST4
5355 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5356 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5357 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5358 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5359 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5360 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5361 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5362 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5363 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5364 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5365 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5366 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5367 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5368 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5369 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5370 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5371 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5372 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005373 }
5374}
5375
Jim Grosbach1a747242012-01-23 23:45:44 +00005376static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005377 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00005378 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005379 // VLD1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005380 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5381 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5382 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5383 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5384 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5385 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5386 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5387 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5388 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005389
5390 // VLD2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005391 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5392 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5393 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5394 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5395 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5396 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5397 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5398 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5399 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5400 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5401 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5402 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5403 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5404 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5405 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005406
Jim Grosbachb78403c2012-01-24 23:47:04 +00005407 // VLD3DUP
5408 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5409 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5410 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5411 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5412 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5413 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5414 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5415 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5416 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5417 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5418 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5419 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5420 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5421 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5422 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5423 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5424 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5425 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5426
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005427 // VLD3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005428 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5429 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5430 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5431 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5432 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5433 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5434 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5435 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5436 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5437 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5438 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5439 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5440 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5441 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5442 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005443
5444 // VLD3
Jim Grosbach1e946a42012-01-24 00:43:12 +00005445 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5446 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5447 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5448 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5449 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5450 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5451 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5452 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5453 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5454 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5455 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5456 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5457 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5458 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5459 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5460 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5461 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5462 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbached561fc2012-01-24 00:43:17 +00005463
Jim Grosbach14952a02012-01-24 18:37:25 +00005464 // VLD4LN
5465 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5466 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5467 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5468 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5469 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5470 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5471 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5472 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5473 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5474 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5475 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5476 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5477 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5478 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5479 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5480
Jim Grosbach086cbfa2012-01-25 00:01:08 +00005481 // VLD4DUP
5482 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5483 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5484 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5485 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5486 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5487 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5488 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5489 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5490 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5491 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5492 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5493 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5494 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5495 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5496 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5497 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5498 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5499 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5500
Jim Grosbached561fc2012-01-24 00:43:17 +00005501 // VLD4
5502 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5503 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5504 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5505 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5506 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5507 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5508 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5509 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5510 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5511 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5512 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5513 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5514 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5515 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5516 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5517 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5518 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5519 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005520 }
5521}
5522
Jim Grosbachafad0532011-11-10 23:42:14 +00005523bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005524processInstruction(MCInst &Inst,
5525 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5526 switch (Inst.getOpcode()) {
Jim Grosbach94298a92012-01-18 22:46:46 +00005527 // Aliases for alternate PC+imm syntax of LDR instructions.
5528 case ARM::t2LDRpcrel:
5529 Inst.setOpcode(ARM::t2LDRpci);
5530 return true;
5531 case ARM::t2LDRBpcrel:
5532 Inst.setOpcode(ARM::t2LDRBpci);
5533 return true;
5534 case ARM::t2LDRHpcrel:
5535 Inst.setOpcode(ARM::t2LDRHpci);
5536 return true;
5537 case ARM::t2LDRSBpcrel:
5538 Inst.setOpcode(ARM::t2LDRSBpci);
5539 return true;
5540 case ARM::t2LDRSHpcrel:
5541 Inst.setOpcode(ARM::t2LDRSHpci);
5542 return true;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005543 // Handle NEON VST complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005544 case ARM::VST1LNdWB_register_Asm_8:
5545 case ARM::VST1LNdWB_register_Asm_16:
5546 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005547 MCInst TmpInst;
5548 // Shuffle the operands around so the lane index operand is in the
5549 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005550 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005551 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005552 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5553 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5554 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5555 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5556 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5557 TmpInst.addOperand(Inst.getOperand(1)); // lane
5558 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5559 TmpInst.addOperand(Inst.getOperand(6));
5560 Inst = TmpInst;
5561 return true;
5562 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005563
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005564 case ARM::VST2LNdWB_register_Asm_8:
5565 case ARM::VST2LNdWB_register_Asm_16:
5566 case ARM::VST2LNdWB_register_Asm_32:
5567 case ARM::VST2LNqWB_register_Asm_16:
5568 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005569 MCInst TmpInst;
5570 // Shuffle the operands around so the lane index operand is in the
5571 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005572 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005573 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005574 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5575 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5576 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5577 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5578 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005579 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5580 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005581 TmpInst.addOperand(Inst.getOperand(1)); // lane
5582 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5583 TmpInst.addOperand(Inst.getOperand(6));
5584 Inst = TmpInst;
5585 return true;
5586 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005587
5588 case ARM::VST3LNdWB_register_Asm_8:
5589 case ARM::VST3LNdWB_register_Asm_16:
5590 case ARM::VST3LNdWB_register_Asm_32:
5591 case ARM::VST3LNqWB_register_Asm_16:
5592 case ARM::VST3LNqWB_register_Asm_32: {
5593 MCInst TmpInst;
5594 // Shuffle the operands around so the lane index operand is in the
5595 // right place.
5596 unsigned Spacing;
5597 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5598 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5599 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5600 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5601 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5602 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5603 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5604 Spacing));
5605 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5606 Spacing * 2));
5607 TmpInst.addOperand(Inst.getOperand(1)); // lane
5608 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5609 TmpInst.addOperand(Inst.getOperand(6));
5610 Inst = TmpInst;
5611 return true;
5612 }
5613
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005614 case ARM::VST4LNdWB_register_Asm_8:
5615 case ARM::VST4LNdWB_register_Asm_16:
5616 case ARM::VST4LNdWB_register_Asm_32:
5617 case ARM::VST4LNqWB_register_Asm_16:
5618 case ARM::VST4LNqWB_register_Asm_32: {
5619 MCInst TmpInst;
5620 // Shuffle the operands around so the lane index operand is in the
5621 // right place.
5622 unsigned Spacing;
5623 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5624 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5625 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5626 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5627 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5628 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5629 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5630 Spacing));
5631 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5632 Spacing * 2));
5633 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5634 Spacing * 3));
5635 TmpInst.addOperand(Inst.getOperand(1)); // lane
5636 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5637 TmpInst.addOperand(Inst.getOperand(6));
5638 Inst = TmpInst;
5639 return true;
5640 }
5641
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005642 case ARM::VST1LNdWB_fixed_Asm_8:
5643 case ARM::VST1LNdWB_fixed_Asm_16:
5644 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005645 MCInst TmpInst;
5646 // Shuffle the operands around so the lane index operand is in the
5647 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005648 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005649 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005650 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5651 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5652 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5653 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5654 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5655 TmpInst.addOperand(Inst.getOperand(1)); // lane
5656 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5657 TmpInst.addOperand(Inst.getOperand(5));
5658 Inst = TmpInst;
5659 return true;
5660 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005661
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005662 case ARM::VST2LNdWB_fixed_Asm_8:
5663 case ARM::VST2LNdWB_fixed_Asm_16:
5664 case ARM::VST2LNdWB_fixed_Asm_32:
5665 case ARM::VST2LNqWB_fixed_Asm_16:
5666 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005667 MCInst TmpInst;
5668 // Shuffle the operands around so the lane index operand is in the
5669 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005670 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005671 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005672 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5673 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5674 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5675 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5676 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005677 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5678 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005679 TmpInst.addOperand(Inst.getOperand(1)); // lane
5680 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5681 TmpInst.addOperand(Inst.getOperand(5));
5682 Inst = TmpInst;
5683 return true;
5684 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005685
5686 case ARM::VST3LNdWB_fixed_Asm_8:
5687 case ARM::VST3LNdWB_fixed_Asm_16:
5688 case ARM::VST3LNdWB_fixed_Asm_32:
5689 case ARM::VST3LNqWB_fixed_Asm_16:
5690 case ARM::VST3LNqWB_fixed_Asm_32: {
5691 MCInst TmpInst;
5692 // Shuffle the operands around so the lane index operand is in the
5693 // right place.
5694 unsigned Spacing;
5695 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5696 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5697 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5698 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5699 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5700 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5701 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5702 Spacing));
5703 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5704 Spacing * 2));
5705 TmpInst.addOperand(Inst.getOperand(1)); // lane
5706 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5707 TmpInst.addOperand(Inst.getOperand(5));
5708 Inst = TmpInst;
5709 return true;
5710 }
5711
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005712 case ARM::VST4LNdWB_fixed_Asm_8:
5713 case ARM::VST4LNdWB_fixed_Asm_16:
5714 case ARM::VST4LNdWB_fixed_Asm_32:
5715 case ARM::VST4LNqWB_fixed_Asm_16:
5716 case ARM::VST4LNqWB_fixed_Asm_32: {
5717 MCInst TmpInst;
5718 // Shuffle the operands around so the lane index operand is in the
5719 // right place.
5720 unsigned Spacing;
5721 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5722 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5723 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5724 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5725 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5726 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5727 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5728 Spacing));
5729 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5730 Spacing * 2));
5731 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5732 Spacing * 3));
5733 TmpInst.addOperand(Inst.getOperand(1)); // lane
5734 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5735 TmpInst.addOperand(Inst.getOperand(5));
5736 Inst = TmpInst;
5737 return true;
5738 }
5739
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005740 case ARM::VST1LNdAsm_8:
5741 case ARM::VST1LNdAsm_16:
5742 case ARM::VST1LNdAsm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005743 MCInst TmpInst;
5744 // Shuffle the operands around so the lane index operand is in the
5745 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005746 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005747 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005748 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5749 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5750 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5751 TmpInst.addOperand(Inst.getOperand(1)); // lane
5752 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5753 TmpInst.addOperand(Inst.getOperand(5));
5754 Inst = TmpInst;
5755 return true;
5756 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005757
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005758 case ARM::VST2LNdAsm_8:
5759 case ARM::VST2LNdAsm_16:
5760 case ARM::VST2LNdAsm_32:
5761 case ARM::VST2LNqAsm_16:
5762 case ARM::VST2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005763 MCInst TmpInst;
5764 // Shuffle the operands around so the lane index operand is in the
5765 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005766 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005767 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005768 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5769 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5770 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005771 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5772 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005773 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 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005779
5780 case ARM::VST3LNdAsm_8:
5781 case ARM::VST3LNdAsm_16:
5782 case ARM::VST3LNdAsm_32:
5783 case ARM::VST3LNqAsm_16:
5784 case ARM::VST3LNqAsm_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
5791 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5792 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5793 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5794 Spacing));
5795 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5796 Spacing * 2));
5797 TmpInst.addOperand(Inst.getOperand(1)); // lane
5798 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5799 TmpInst.addOperand(Inst.getOperand(5));
5800 Inst = TmpInst;
5801 return true;
5802 }
5803
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005804 case ARM::VST4LNdAsm_8:
5805 case ARM::VST4LNdAsm_16:
5806 case ARM::VST4LNdAsm_32:
5807 case ARM::VST4LNqAsm_16:
5808 case ARM::VST4LNqAsm_32: {
5809 MCInst TmpInst;
5810 // Shuffle the operands around so the lane index operand is in the
5811 // right place.
5812 unsigned Spacing;
5813 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5814 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5815 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5816 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5817 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5818 Spacing));
5819 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5820 Spacing * 2));
5821 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5822 Spacing * 3));
5823 TmpInst.addOperand(Inst.getOperand(1)); // lane
5824 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5825 TmpInst.addOperand(Inst.getOperand(5));
5826 Inst = TmpInst;
5827 return true;
5828 }
5829
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005830 // Handle NEON VLD complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005831 case ARM::VLD1LNdWB_register_Asm_8:
5832 case ARM::VLD1LNdWB_register_Asm_16:
5833 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005834 MCInst TmpInst;
5835 // Shuffle the operands around so the lane index operand is in the
5836 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005837 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005838 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005839 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5840 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5841 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5842 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5843 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5844 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5845 TmpInst.addOperand(Inst.getOperand(1)); // lane
5846 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5847 TmpInst.addOperand(Inst.getOperand(6));
5848 Inst = TmpInst;
5849 return true;
5850 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005851
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005852 case ARM::VLD2LNdWB_register_Asm_8:
5853 case ARM::VLD2LNdWB_register_Asm_16:
5854 case ARM::VLD2LNdWB_register_Asm_32:
5855 case ARM::VLD2LNqWB_register_Asm_16:
5856 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005857 MCInst TmpInst;
5858 // Shuffle the operands around so the lane index operand is in the
5859 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005860 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005861 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005862 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005863 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5864 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005865 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5866 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5867 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5868 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5869 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005870 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5871 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005872 TmpInst.addOperand(Inst.getOperand(1)); // lane
5873 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5874 TmpInst.addOperand(Inst.getOperand(6));
5875 Inst = TmpInst;
5876 return true;
5877 }
5878
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005879 case ARM::VLD3LNdWB_register_Asm_8:
5880 case ARM::VLD3LNdWB_register_Asm_16:
5881 case ARM::VLD3LNdWB_register_Asm_32:
5882 case ARM::VLD3LNqWB_register_Asm_16:
5883 case ARM::VLD3LNqWB_register_Asm_32: {
5884 MCInst TmpInst;
5885 // Shuffle the operands around so the lane index operand is in the
5886 // right place.
5887 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005888 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005889 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5890 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5891 Spacing));
5892 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005893 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005894 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5895 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5896 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5897 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5898 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5899 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5900 Spacing));
5901 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005902 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005903 TmpInst.addOperand(Inst.getOperand(1)); // lane
5904 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5905 TmpInst.addOperand(Inst.getOperand(6));
5906 Inst = TmpInst;
5907 return true;
5908 }
5909
Jim Grosbach14952a02012-01-24 18:37:25 +00005910 case ARM::VLD4LNdWB_register_Asm_8:
5911 case ARM::VLD4LNdWB_register_Asm_16:
5912 case ARM::VLD4LNdWB_register_Asm_32:
5913 case ARM::VLD4LNqWB_register_Asm_16:
5914 case ARM::VLD4LNqWB_register_Asm_32: {
5915 MCInst TmpInst;
5916 // Shuffle the operands around so the lane index operand is in the
5917 // right place.
5918 unsigned Spacing;
5919 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5920 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5921 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5922 Spacing));
5923 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5924 Spacing * 2));
5925 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5926 Spacing * 3));
5927 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5928 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5929 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5930 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5931 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5932 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5933 Spacing));
5934 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5935 Spacing * 2));
5936 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5937 Spacing * 3));
5938 TmpInst.addOperand(Inst.getOperand(1)); // lane
5939 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5940 TmpInst.addOperand(Inst.getOperand(6));
5941 Inst = TmpInst;
5942 return true;
5943 }
5944
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005945 case ARM::VLD1LNdWB_fixed_Asm_8:
5946 case ARM::VLD1LNdWB_fixed_Asm_16:
5947 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005948 MCInst TmpInst;
5949 // Shuffle the operands around so the lane index operand is in the
5950 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005951 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005952 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005953 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5954 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5955 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5956 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5957 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5958 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5959 TmpInst.addOperand(Inst.getOperand(1)); // lane
5960 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5961 TmpInst.addOperand(Inst.getOperand(5));
5962 Inst = TmpInst;
5963 return true;
5964 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005965
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005966 case ARM::VLD2LNdWB_fixed_Asm_8:
5967 case ARM::VLD2LNdWB_fixed_Asm_16:
5968 case ARM::VLD2LNdWB_fixed_Asm_32:
5969 case ARM::VLD2LNqWB_fixed_Asm_16:
5970 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005971 MCInst TmpInst;
5972 // Shuffle the operands around so the lane index operand is in the
5973 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005974 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005975 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005976 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005977 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5978 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005979 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5980 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5981 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5982 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5983 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005984 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5985 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005986 TmpInst.addOperand(Inst.getOperand(1)); // lane
5987 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5988 TmpInst.addOperand(Inst.getOperand(5));
5989 Inst = TmpInst;
5990 return true;
5991 }
5992
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005993 case ARM::VLD3LNdWB_fixed_Asm_8:
5994 case ARM::VLD3LNdWB_fixed_Asm_16:
5995 case ARM::VLD3LNdWB_fixed_Asm_32:
5996 case ARM::VLD3LNqWB_fixed_Asm_16:
5997 case ARM::VLD3LNqWB_fixed_Asm_32: {
5998 MCInst TmpInst;
5999 // Shuffle the operands around so the lane index operand is in the
6000 // right place.
6001 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006002 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006003 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6004 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6005 Spacing));
6006 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006007 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006008 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6009 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6010 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6011 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6012 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6013 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6014 Spacing));
6015 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006016 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006017 TmpInst.addOperand(Inst.getOperand(1)); // lane
6018 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6019 TmpInst.addOperand(Inst.getOperand(5));
6020 Inst = TmpInst;
6021 return true;
6022 }
6023
Jim Grosbach14952a02012-01-24 18:37:25 +00006024 case ARM::VLD4LNdWB_fixed_Asm_8:
6025 case ARM::VLD4LNdWB_fixed_Asm_16:
6026 case ARM::VLD4LNdWB_fixed_Asm_32:
6027 case ARM::VLD4LNqWB_fixed_Asm_16:
6028 case ARM::VLD4LNqWB_fixed_Asm_32: {
6029 MCInst TmpInst;
6030 // Shuffle the operands around so the lane index operand is in the
6031 // right place.
6032 unsigned Spacing;
6033 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6034 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6035 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6036 Spacing));
6037 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6038 Spacing * 2));
6039 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6040 Spacing * 3));
6041 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6042 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6043 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6044 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6045 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6046 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6047 Spacing));
6048 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6049 Spacing * 2));
6050 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6051 Spacing * 3));
6052 TmpInst.addOperand(Inst.getOperand(1)); // lane
6053 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6054 TmpInst.addOperand(Inst.getOperand(5));
6055 Inst = TmpInst;
6056 return true;
6057 }
6058
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006059 case ARM::VLD1LNdAsm_8:
6060 case ARM::VLD1LNdAsm_16:
6061 case ARM::VLD1LNdAsm_32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00006062 MCInst TmpInst;
6063 // Shuffle the operands around so the lane index operand is in the
6064 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006065 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006066 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach04945c42011-12-02 00:35:16 +00006067 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6068 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6069 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6070 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6071 TmpInst.addOperand(Inst.getOperand(1)); // lane
6072 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6073 TmpInst.addOperand(Inst.getOperand(5));
6074 Inst = TmpInst;
6075 return true;
6076 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006077
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006078 case ARM::VLD2LNdAsm_8:
6079 case ARM::VLD2LNdAsm_16:
6080 case ARM::VLD2LNdAsm_32:
6081 case ARM::VLD2LNqAsm_16:
6082 case ARM::VLD2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006083 MCInst TmpInst;
6084 // Shuffle the operands around so the lane index operand is in the
6085 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006086 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006087 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006088 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006089 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6090 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006091 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6092 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6093 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006094 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6095 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006096 TmpInst.addOperand(Inst.getOperand(1)); // lane
6097 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6098 TmpInst.addOperand(Inst.getOperand(5));
6099 Inst = TmpInst;
6100 return true;
6101 }
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006102
6103 case ARM::VLD3LNdAsm_8:
6104 case ARM::VLD3LNdAsm_16:
6105 case ARM::VLD3LNdAsm_32:
6106 case ARM::VLD3LNqAsm_16:
6107 case ARM::VLD3LNqAsm_32: {
6108 MCInst TmpInst;
6109 // Shuffle the operands around so the lane index operand is in the
6110 // right place.
6111 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006112 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006113 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6114 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6115 Spacing));
6116 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006117 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006118 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6119 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6120 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6121 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6122 Spacing));
6123 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006124 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006125 TmpInst.addOperand(Inst.getOperand(1)); // lane
6126 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6127 TmpInst.addOperand(Inst.getOperand(5));
6128 Inst = TmpInst;
6129 return true;
6130 }
6131
Jim Grosbach14952a02012-01-24 18:37:25 +00006132 case ARM::VLD4LNdAsm_8:
6133 case ARM::VLD4LNdAsm_16:
6134 case ARM::VLD4LNdAsm_32:
6135 case ARM::VLD4LNqAsm_16:
6136 case ARM::VLD4LNqAsm_32: {
6137 MCInst TmpInst;
6138 // Shuffle the operands around so the lane index operand is in the
6139 // right place.
6140 unsigned Spacing;
6141 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6142 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6143 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6144 Spacing));
6145 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6146 Spacing * 2));
6147 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6148 Spacing * 3));
6149 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6150 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6151 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6152 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6153 Spacing));
6154 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6155 Spacing * 2));
6156 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6157 Spacing * 3));
6158 TmpInst.addOperand(Inst.getOperand(1)); // lane
6159 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6160 TmpInst.addOperand(Inst.getOperand(5));
6161 Inst = TmpInst;
6162 return true;
6163 }
6164
Jim Grosbachb78403c2012-01-24 23:47:04 +00006165 // VLD3DUP single 3-element structure to all lanes instructions.
6166 case ARM::VLD3DUPdAsm_8:
6167 case ARM::VLD3DUPdAsm_16:
6168 case ARM::VLD3DUPdAsm_32:
6169 case ARM::VLD3DUPqAsm_8:
6170 case ARM::VLD3DUPqAsm_16:
6171 case ARM::VLD3DUPqAsm_32: {
6172 MCInst TmpInst;
6173 unsigned Spacing;
6174 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6175 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6176 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6177 Spacing));
6178 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6179 Spacing * 2));
6180 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6181 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6182 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6183 TmpInst.addOperand(Inst.getOperand(4));
6184 Inst = TmpInst;
6185 return true;
6186 }
6187
6188 case ARM::VLD3DUPdWB_fixed_Asm_8:
6189 case ARM::VLD3DUPdWB_fixed_Asm_16:
6190 case ARM::VLD3DUPdWB_fixed_Asm_32:
6191 case ARM::VLD3DUPqWB_fixed_Asm_8:
6192 case ARM::VLD3DUPqWB_fixed_Asm_16:
6193 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6194 MCInst TmpInst;
6195 unsigned Spacing;
6196 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6197 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6198 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6199 Spacing));
6200 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6201 Spacing * 2));
6202 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6203 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6204 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6205 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6206 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6207 TmpInst.addOperand(Inst.getOperand(4));
6208 Inst = TmpInst;
6209 return true;
6210 }
6211
6212 case ARM::VLD3DUPdWB_register_Asm_8:
6213 case ARM::VLD3DUPdWB_register_Asm_16:
6214 case ARM::VLD3DUPdWB_register_Asm_32:
6215 case ARM::VLD3DUPqWB_register_Asm_8:
6216 case ARM::VLD3DUPqWB_register_Asm_16:
6217 case ARM::VLD3DUPqWB_register_Asm_32: {
6218 MCInst TmpInst;
6219 unsigned Spacing;
6220 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6221 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6222 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6223 Spacing));
6224 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6225 Spacing * 2));
6226 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6227 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6228 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6229 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6230 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6231 TmpInst.addOperand(Inst.getOperand(5));
6232 Inst = TmpInst;
6233 return true;
6234 }
6235
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006236 // VLD3 multiple 3-element structure instructions.
6237 case ARM::VLD3dAsm_8:
6238 case ARM::VLD3dAsm_16:
6239 case ARM::VLD3dAsm_32:
6240 case ARM::VLD3qAsm_8:
6241 case ARM::VLD3qAsm_16:
6242 case ARM::VLD3qAsm_32: {
6243 MCInst TmpInst;
6244 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006245 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006246 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6247 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6248 Spacing));
6249 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6250 Spacing * 2));
6251 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6252 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6253 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6254 TmpInst.addOperand(Inst.getOperand(4));
6255 Inst = TmpInst;
6256 return true;
6257 }
6258
6259 case ARM::VLD3dWB_fixed_Asm_8:
6260 case ARM::VLD3dWB_fixed_Asm_16:
6261 case ARM::VLD3dWB_fixed_Asm_32:
6262 case ARM::VLD3qWB_fixed_Asm_8:
6263 case ARM::VLD3qWB_fixed_Asm_16:
6264 case ARM::VLD3qWB_fixed_Asm_32: {
6265 MCInst TmpInst;
6266 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006267 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006268 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6269 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6270 Spacing));
6271 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6272 Spacing * 2));
6273 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6274 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6275 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6276 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6277 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6278 TmpInst.addOperand(Inst.getOperand(4));
6279 Inst = TmpInst;
6280 return true;
6281 }
6282
6283 case ARM::VLD3dWB_register_Asm_8:
6284 case ARM::VLD3dWB_register_Asm_16:
6285 case ARM::VLD3dWB_register_Asm_32:
6286 case ARM::VLD3qWB_register_Asm_8:
6287 case ARM::VLD3qWB_register_Asm_16:
6288 case ARM::VLD3qWB_register_Asm_32: {
6289 MCInst TmpInst;
6290 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006291 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006292 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6293 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6294 Spacing));
6295 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6296 Spacing * 2));
6297 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6298 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6299 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6300 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6301 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6302 TmpInst.addOperand(Inst.getOperand(5));
6303 Inst = TmpInst;
6304 return true;
6305 }
6306
Jim Grosbach086cbfa2012-01-25 00:01:08 +00006307 // VLD4DUP single 3-element structure to all lanes instructions.
6308 case ARM::VLD4DUPdAsm_8:
6309 case ARM::VLD4DUPdAsm_16:
6310 case ARM::VLD4DUPdAsm_32:
6311 case ARM::VLD4DUPqAsm_8:
6312 case ARM::VLD4DUPqAsm_16:
6313 case ARM::VLD4DUPqAsm_32: {
6314 MCInst TmpInst;
6315 unsigned Spacing;
6316 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6317 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6318 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6319 Spacing));
6320 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6321 Spacing * 2));
6322 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6323 Spacing * 3));
6324 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6325 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6326 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6327 TmpInst.addOperand(Inst.getOperand(4));
6328 Inst = TmpInst;
6329 return true;
6330 }
6331
6332 case ARM::VLD4DUPdWB_fixed_Asm_8:
6333 case ARM::VLD4DUPdWB_fixed_Asm_16:
6334 case ARM::VLD4DUPdWB_fixed_Asm_32:
6335 case ARM::VLD4DUPqWB_fixed_Asm_8:
6336 case ARM::VLD4DUPqWB_fixed_Asm_16:
6337 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6338 MCInst TmpInst;
6339 unsigned Spacing;
6340 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6341 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6342 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6343 Spacing));
6344 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6345 Spacing * 2));
6346 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6347 Spacing * 3));
6348 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6349 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6350 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6351 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6352 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6353 TmpInst.addOperand(Inst.getOperand(4));
6354 Inst = TmpInst;
6355 return true;
6356 }
6357
6358 case ARM::VLD4DUPdWB_register_Asm_8:
6359 case ARM::VLD4DUPdWB_register_Asm_16:
6360 case ARM::VLD4DUPdWB_register_Asm_32:
6361 case ARM::VLD4DUPqWB_register_Asm_8:
6362 case ARM::VLD4DUPqWB_register_Asm_16:
6363 case ARM::VLD4DUPqWB_register_Asm_32: {
6364 MCInst TmpInst;
6365 unsigned Spacing;
6366 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6367 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6368 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6369 Spacing));
6370 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6371 Spacing * 2));
6372 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6373 Spacing * 3));
6374 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6375 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6376 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6377 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6378 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6379 TmpInst.addOperand(Inst.getOperand(5));
6380 Inst = TmpInst;
6381 return true;
6382 }
6383
6384 // VLD4 multiple 4-element structure instructions.
Jim Grosbached561fc2012-01-24 00:43:17 +00006385 case ARM::VLD4dAsm_8:
6386 case ARM::VLD4dAsm_16:
6387 case ARM::VLD4dAsm_32:
6388 case ARM::VLD4qAsm_8:
6389 case ARM::VLD4qAsm_16:
6390 case ARM::VLD4qAsm_32: {
6391 MCInst TmpInst;
6392 unsigned Spacing;
6393 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6394 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6395 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6396 Spacing));
6397 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6398 Spacing * 2));
6399 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6400 Spacing * 3));
6401 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6402 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6403 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6404 TmpInst.addOperand(Inst.getOperand(4));
6405 Inst = TmpInst;
6406 return true;
6407 }
6408
6409 case ARM::VLD4dWB_fixed_Asm_8:
6410 case ARM::VLD4dWB_fixed_Asm_16:
6411 case ARM::VLD4dWB_fixed_Asm_32:
6412 case ARM::VLD4qWB_fixed_Asm_8:
6413 case ARM::VLD4qWB_fixed_Asm_16:
6414 case ARM::VLD4qWB_fixed_Asm_32: {
6415 MCInst TmpInst;
6416 unsigned Spacing;
6417 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6418 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6419 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6420 Spacing));
6421 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6422 Spacing * 2));
6423 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6424 Spacing * 3));
6425 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6426 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6427 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6428 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6429 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6430 TmpInst.addOperand(Inst.getOperand(4));
6431 Inst = TmpInst;
6432 return true;
6433 }
6434
6435 case ARM::VLD4dWB_register_Asm_8:
6436 case ARM::VLD4dWB_register_Asm_16:
6437 case ARM::VLD4dWB_register_Asm_32:
6438 case ARM::VLD4qWB_register_Asm_8:
6439 case ARM::VLD4qWB_register_Asm_16:
6440 case ARM::VLD4qWB_register_Asm_32: {
6441 MCInst TmpInst;
6442 unsigned Spacing;
6443 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6444 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6445 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6446 Spacing));
6447 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6448 Spacing * 2));
6449 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6450 Spacing * 3));
6451 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6452 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6453 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6454 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6455 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6456 TmpInst.addOperand(Inst.getOperand(5));
6457 Inst = TmpInst;
6458 return true;
6459 }
6460
Jim Grosbach1a747242012-01-23 23:45:44 +00006461 // VST3 multiple 3-element structure instructions.
6462 case ARM::VST3dAsm_8:
6463 case ARM::VST3dAsm_16:
6464 case ARM::VST3dAsm_32:
6465 case ARM::VST3qAsm_8:
6466 case ARM::VST3qAsm_16:
6467 case ARM::VST3qAsm_32: {
6468 MCInst TmpInst;
6469 unsigned Spacing;
6470 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6471 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6472 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6473 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6474 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6475 Spacing));
6476 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6477 Spacing * 2));
6478 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6479 TmpInst.addOperand(Inst.getOperand(4));
6480 Inst = TmpInst;
6481 return true;
6482 }
6483
6484 case ARM::VST3dWB_fixed_Asm_8:
6485 case ARM::VST3dWB_fixed_Asm_16:
6486 case ARM::VST3dWB_fixed_Asm_32:
6487 case ARM::VST3qWB_fixed_Asm_8:
6488 case ARM::VST3qWB_fixed_Asm_16:
6489 case ARM::VST3qWB_fixed_Asm_32: {
6490 MCInst TmpInst;
6491 unsigned Spacing;
6492 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
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(0)); // Vd
6498 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6499 Spacing));
6500 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6501 Spacing * 2));
6502 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6503 TmpInst.addOperand(Inst.getOperand(4));
6504 Inst = TmpInst;
6505 return true;
6506 }
6507
6508 case ARM::VST3dWB_register_Asm_8:
6509 case ARM::VST3dWB_register_Asm_16:
6510 case ARM::VST3dWB_register_Asm_32:
6511 case ARM::VST3qWB_register_Asm_8:
6512 case ARM::VST3qWB_register_Asm_16:
6513 case ARM::VST3qWB_register_Asm_32: {
6514 MCInst TmpInst;
6515 unsigned Spacing;
6516 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6517 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6518 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6519 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6520 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6521 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6522 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6523 Spacing));
6524 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6525 Spacing * 2));
6526 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6527 TmpInst.addOperand(Inst.getOperand(5));
6528 Inst = TmpInst;
6529 return true;
6530 }
6531
Jim Grosbachda70eac2012-01-24 00:58:13 +00006532 // VST4 multiple 3-element structure instructions.
6533 case ARM::VST4dAsm_8:
6534 case ARM::VST4dAsm_16:
6535 case ARM::VST4dAsm_32:
6536 case ARM::VST4qAsm_8:
6537 case ARM::VST4qAsm_16:
6538 case ARM::VST4qAsm_32: {
6539 MCInst TmpInst;
6540 unsigned Spacing;
6541 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6542 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6543 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6544 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6545 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6546 Spacing));
6547 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6548 Spacing * 2));
6549 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6550 Spacing * 3));
6551 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6552 TmpInst.addOperand(Inst.getOperand(4));
6553 Inst = TmpInst;
6554 return true;
6555 }
6556
6557 case ARM::VST4dWB_fixed_Asm_8:
6558 case ARM::VST4dWB_fixed_Asm_16:
6559 case ARM::VST4dWB_fixed_Asm_32:
6560 case ARM::VST4qWB_fixed_Asm_8:
6561 case ARM::VST4qWB_fixed_Asm_16:
6562 case ARM::VST4qWB_fixed_Asm_32: {
6563 MCInst TmpInst;
6564 unsigned Spacing;
6565 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6566 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6567 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6568 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6569 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6570 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6571 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6572 Spacing));
6573 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6574 Spacing * 2));
6575 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6576 Spacing * 3));
6577 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6578 TmpInst.addOperand(Inst.getOperand(4));
6579 Inst = TmpInst;
6580 return true;
6581 }
6582
6583 case ARM::VST4dWB_register_Asm_8:
6584 case ARM::VST4dWB_register_Asm_16:
6585 case ARM::VST4dWB_register_Asm_32:
6586 case ARM::VST4qWB_register_Asm_8:
6587 case ARM::VST4qWB_register_Asm_16:
6588 case ARM::VST4qWB_register_Asm_32: {
6589 MCInst TmpInst;
6590 unsigned Spacing;
6591 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6592 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6593 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6594 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6595 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6596 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6597 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6598 Spacing));
6599 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6600 Spacing * 2));
6601 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6602 Spacing * 3));
6603 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6604 TmpInst.addOperand(Inst.getOperand(5));
6605 Inst = TmpInst;
6606 return true;
6607 }
6608
Jim Grosbach485e5622011-12-13 22:45:11 +00006609 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbachb3ef7132011-12-21 20:54:00 +00006610 case ARM::t2MOVsr:
6611 case ARM::t2MOVSsr: {
6612 // Which instruction to expand to depends on the CCOut operand and
6613 // whether we're in an IT block if the register operands are low
6614 // registers.
6615 bool isNarrow = false;
6616 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6617 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6618 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6619 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6620 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6621 isNarrow = true;
6622 MCInst TmpInst;
6623 unsigned newOpc;
6624 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6625 default: llvm_unreachable("unexpected opcode!");
6626 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6627 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6628 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6629 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6630 }
6631 TmpInst.setOpcode(newOpc);
6632 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6633 if (isNarrow)
6634 TmpInst.addOperand(MCOperand::CreateReg(
6635 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6636 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6637 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6638 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6639 TmpInst.addOperand(Inst.getOperand(5));
6640 if (!isNarrow)
6641 TmpInst.addOperand(MCOperand::CreateReg(
6642 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6643 Inst = TmpInst;
6644 return true;
6645 }
Jim Grosbach485e5622011-12-13 22:45:11 +00006646 case ARM::t2MOVsi:
6647 case ARM::t2MOVSsi: {
6648 // Which instruction to expand to depends on the CCOut operand and
6649 // whether we're in an IT block if the register operands are low
6650 // registers.
6651 bool isNarrow = false;
6652 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6653 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6654 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6655 isNarrow = true;
6656 MCInst TmpInst;
6657 unsigned newOpc;
6658 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6659 default: llvm_unreachable("unexpected opcode!");
6660 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6661 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6662 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6663 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00006664 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach485e5622011-12-13 22:45:11 +00006665 }
6666 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6667 if (Ammount == 32) Ammount = 0;
6668 TmpInst.setOpcode(newOpc);
6669 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6670 if (isNarrow)
6671 TmpInst.addOperand(MCOperand::CreateReg(
6672 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6673 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00006674 if (newOpc != ARM::t2RRX)
6675 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach485e5622011-12-13 22:45:11 +00006676 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6677 TmpInst.addOperand(Inst.getOperand(4));
6678 if (!isNarrow)
6679 TmpInst.addOperand(MCOperand::CreateReg(
6680 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6681 Inst = TmpInst;
6682 return true;
6683 }
6684 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00006685 case ARM::ASRr:
6686 case ARM::LSRr:
6687 case ARM::LSLr:
6688 case ARM::RORr: {
6689 ARM_AM::ShiftOpc ShiftTy;
6690 switch(Inst.getOpcode()) {
6691 default: llvm_unreachable("unexpected opcode!");
6692 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6693 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6694 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6695 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6696 }
Jim Grosbachabcac562011-11-16 18:31:45 +00006697 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6698 MCInst TmpInst;
6699 TmpInst.setOpcode(ARM::MOVsr);
6700 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6701 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6702 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6703 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6704 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6705 TmpInst.addOperand(Inst.getOperand(4));
6706 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6707 Inst = TmpInst;
6708 return true;
6709 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00006710 case ARM::ASRi:
6711 case ARM::LSRi:
6712 case ARM::LSLi:
6713 case ARM::RORi: {
6714 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00006715 switch(Inst.getOpcode()) {
6716 default: llvm_unreachable("unexpected opcode!");
6717 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6718 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6719 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6720 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6721 }
6722 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00006723 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00006724 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6725 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00006726 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00006727 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00006728 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6729 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00006730 if (Opc == ARM::MOVsi)
6731 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00006732 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6733 TmpInst.addOperand(Inst.getOperand(4));
6734 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6735 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006736 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00006737 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00006738 case ARM::RRXi: {
6739 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6740 MCInst TmpInst;
6741 TmpInst.setOpcode(ARM::MOVsi);
6742 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6743 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6744 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6745 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6746 TmpInst.addOperand(Inst.getOperand(3));
6747 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6748 Inst = TmpInst;
6749 return true;
6750 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00006751 case ARM::t2LDMIA_UPD: {
6752 // If this is a load of a single register, then we should use
6753 // a post-indexed LDR instruction instead, per the ARM ARM.
6754 if (Inst.getNumOperands() != 5)
6755 return false;
6756 MCInst TmpInst;
6757 TmpInst.setOpcode(ARM::t2LDR_POST);
6758 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6759 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6760 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6761 TmpInst.addOperand(MCOperand::CreateImm(4));
6762 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6763 TmpInst.addOperand(Inst.getOperand(3));
6764 Inst = TmpInst;
6765 return true;
6766 }
6767 case ARM::t2STMDB_UPD: {
6768 // If this is a store of a single register, then we should use
6769 // a pre-indexed STR instruction instead, per the ARM ARM.
6770 if (Inst.getNumOperands() != 5)
6771 return false;
6772 MCInst TmpInst;
6773 TmpInst.setOpcode(ARM::t2STR_PRE);
6774 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6775 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6776 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6777 TmpInst.addOperand(MCOperand::CreateImm(-4));
6778 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6779 TmpInst.addOperand(Inst.getOperand(3));
6780 Inst = TmpInst;
6781 return true;
6782 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006783 case ARM::LDMIA_UPD:
6784 // If this is a load of a single register via a 'pop', then we should use
6785 // a post-indexed LDR instruction instead, per the ARM ARM.
6786 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6787 Inst.getNumOperands() == 5) {
6788 MCInst TmpInst;
6789 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6790 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6791 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6792 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6793 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6794 TmpInst.addOperand(MCOperand::CreateImm(4));
6795 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6796 TmpInst.addOperand(Inst.getOperand(3));
6797 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006798 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006799 }
6800 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00006801 case ARM::STMDB_UPD:
6802 // If this is a store of a single register via a 'push', then we should use
6803 // a pre-indexed STR instruction instead, per the ARM ARM.
6804 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6805 Inst.getNumOperands() == 5) {
6806 MCInst TmpInst;
6807 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6808 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6809 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6810 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6811 TmpInst.addOperand(MCOperand::CreateImm(-4));
6812 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6813 TmpInst.addOperand(Inst.getOperand(3));
6814 Inst = TmpInst;
6815 }
6816 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00006817 case ARM::t2ADDri12:
6818 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6819 // mnemonic was used (not "addw"), encoding T3 is preferred.
6820 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6821 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6822 break;
6823 Inst.setOpcode(ARM::t2ADDri);
6824 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6825 break;
6826 case ARM::t2SUBri12:
6827 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6828 // mnemonic was used (not "subw"), encoding T3 is preferred.
6829 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6830 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6831 break;
6832 Inst.setOpcode(ARM::t2SUBri);
6833 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6834 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006835 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00006836 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6837 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6838 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6839 // to encoding T1 if <Rd> is omitted."
Jim Grosbach199ab902012-03-30 16:31:31 +00006840 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006841 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006842 return true;
6843 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006844 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006845 case ARM::tSUBi8:
6846 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6847 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6848 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6849 // to encoding T1 if <Rd> is omitted."
Jim Grosbach199ab902012-03-30 16:31:31 +00006850 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006851 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006852 return true;
6853 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006854 break;
Jim Grosbachdef5e342012-03-30 17:20:40 +00006855 case ARM::t2ADDri:
6856 case ARM::t2SUBri: {
6857 // If the destination and first source operand are the same, and
6858 // the flags are compatible with the current IT status, use encoding T2
6859 // instead of T3. For compatibility with the system 'as'. Make sure the
6860 // wide encoding wasn't explicit.
6861 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
Jim Grosbach74005ae2012-03-30 18:39:43 +00006862 !isARMLowRegister(Inst.getOperand(0).getReg()) ||
Jim Grosbachdef5e342012-03-30 17:20:40 +00006863 (unsigned)Inst.getOperand(2).getImm() > 255 ||
6864 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
6865 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
6866 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6867 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
6868 break;
6869 MCInst TmpInst;
6870 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
6871 ARM::tADDi8 : ARM::tSUBi8);
6872 TmpInst.addOperand(Inst.getOperand(0));
6873 TmpInst.addOperand(Inst.getOperand(5));
6874 TmpInst.addOperand(Inst.getOperand(0));
6875 TmpInst.addOperand(Inst.getOperand(2));
6876 TmpInst.addOperand(Inst.getOperand(3));
6877 TmpInst.addOperand(Inst.getOperand(4));
6878 Inst = TmpInst;
6879 return true;
6880 }
Jim Grosbache489bab2011-12-05 22:16:39 +00006881 case ARM::t2ADDrr: {
6882 // If the destination and first source operand are the same, and
6883 // there's no setting of the flags, use encoding T2 instead of T3.
6884 // Note that this is only for ADD, not SUB. This mirrors the system
6885 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6886 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6887 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00006888 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6889 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00006890 break;
6891 MCInst TmpInst;
6892 TmpInst.setOpcode(ARM::tADDhirr);
6893 TmpInst.addOperand(Inst.getOperand(0));
6894 TmpInst.addOperand(Inst.getOperand(0));
6895 TmpInst.addOperand(Inst.getOperand(2));
6896 TmpInst.addOperand(Inst.getOperand(3));
6897 TmpInst.addOperand(Inst.getOperand(4));
6898 Inst = TmpInst;
6899 return true;
6900 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006901 case ARM::tB:
6902 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006903 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006904 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006905 return true;
6906 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006907 break;
6908 case ARM::t2B:
6909 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006910 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006911 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006912 return true;
6913 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006914 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00006915 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006916 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00006917 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00006918 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00006919 return true;
6920 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00006921 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006922 case ARM::tBcc:
6923 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00006924 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006925 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00006926 return true;
6927 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00006928 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006929 case ARM::tLDMIA: {
6930 // If the register list contains any high registers, or if the writeback
6931 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6932 // instead if we're in Thumb2. Otherwise, this should have generated
6933 // an error in validateInstruction().
6934 unsigned Rn = Inst.getOperand(0).getReg();
6935 bool hasWritebackToken =
6936 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6937 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6938 bool listContainsBase;
6939 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6940 (!listContainsBase && !hasWritebackToken) ||
6941 (listContainsBase && hasWritebackToken)) {
6942 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6943 assert (isThumbTwo());
6944 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6945 // If we're switching to the updating version, we need to insert
6946 // the writeback tied operand.
6947 if (hasWritebackToken)
6948 Inst.insert(Inst.begin(),
6949 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00006950 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006951 }
6952 break;
6953 }
Jim Grosbach099c9762011-09-16 20:50:13 +00006954 case ARM::tSTMIA_UPD: {
6955 // If the register list contains any high registers, we need to use
6956 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6957 // should have generated an error in validateInstruction().
6958 unsigned Rn = Inst.getOperand(0).getReg();
6959 bool listContainsBase;
6960 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6961 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6962 assert (isThumbTwo());
6963 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00006964 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00006965 }
6966 break;
6967 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006968 case ARM::tPOP: {
6969 bool listContainsBase;
6970 // If the register list contains any high registers, we need to use
6971 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6972 // should have generated an error in validateInstruction().
6973 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006974 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006975 assert (isThumbTwo());
6976 Inst.setOpcode(ARM::t2LDMIA_UPD);
6977 // Add the base register and writeback operands.
6978 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6979 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006980 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006981 }
6982 case ARM::tPUSH: {
6983 bool listContainsBase;
6984 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006985 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006986 assert (isThumbTwo());
6987 Inst.setOpcode(ARM::t2STMDB_UPD);
6988 // Add the base register and writeback operands.
6989 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6990 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006991 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006992 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006993 case ARM::t2MOVi: {
6994 // If we can use the 16-bit encoding and the user didn't explicitly
6995 // request the 32-bit variant, transform it here.
6996 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbach199ab902012-03-30 16:31:31 +00006997 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00006998 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6999 Inst.getOperand(4).getReg() == ARM::CPSR) ||
7000 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00007001 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7002 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7003 // The operands aren't in the same order for tMOVi8...
7004 MCInst TmpInst;
7005 TmpInst.setOpcode(ARM::tMOVi8);
7006 TmpInst.addOperand(Inst.getOperand(0));
7007 TmpInst.addOperand(Inst.getOperand(4));
7008 TmpInst.addOperand(Inst.getOperand(1));
7009 TmpInst.addOperand(Inst.getOperand(2));
7010 TmpInst.addOperand(Inst.getOperand(3));
7011 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007012 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00007013 }
7014 break;
7015 }
7016 case ARM::t2MOVr: {
7017 // If we can use the 16-bit encoding and the user didn't explicitly
7018 // request the 32-bit variant, transform it here.
7019 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7020 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7021 Inst.getOperand(2).getImm() == ARMCC::AL &&
7022 Inst.getOperand(4).getReg() == ARM::CPSR &&
7023 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7024 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7025 // The operands aren't the same for tMOV[S]r... (no cc_out)
7026 MCInst TmpInst;
7027 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7028 TmpInst.addOperand(Inst.getOperand(0));
7029 TmpInst.addOperand(Inst.getOperand(1));
7030 TmpInst.addOperand(Inst.getOperand(2));
7031 TmpInst.addOperand(Inst.getOperand(3));
7032 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007033 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00007034 }
7035 break;
7036 }
Jim Grosbach82213192011-09-19 20:29:33 +00007037 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00007038 case ARM::t2SXTB:
7039 case ARM::t2UXTH:
7040 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00007041 // If we can use the 16-bit encoding and the user didn't explicitly
7042 // request the 32-bit variant, transform it here.
7043 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7044 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7045 Inst.getOperand(2).getImm() == 0 &&
7046 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7047 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00007048 unsigned NewOpc;
7049 switch (Inst.getOpcode()) {
7050 default: llvm_unreachable("Illegal opcode!");
7051 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7052 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7053 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7054 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7055 }
Jim Grosbach82213192011-09-19 20:29:33 +00007056 // The operands aren't the same for thumb1 (no rotate operand).
7057 MCInst TmpInst;
7058 TmpInst.setOpcode(NewOpc);
7059 TmpInst.addOperand(Inst.getOperand(0));
7060 TmpInst.addOperand(Inst.getOperand(1));
7061 TmpInst.addOperand(Inst.getOperand(3));
7062 TmpInst.addOperand(Inst.getOperand(4));
7063 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007064 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00007065 }
7066 break;
7067 }
Jim Grosbache2ca9e52011-12-20 00:59:38 +00007068 case ARM::MOVsi: {
7069 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7070 if (SOpc == ARM_AM::rrx) return false;
7071 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7072 // Shifting by zero is accepted as a vanilla 'MOVr'
7073 MCInst TmpInst;
7074 TmpInst.setOpcode(ARM::MOVr);
7075 TmpInst.addOperand(Inst.getOperand(0));
7076 TmpInst.addOperand(Inst.getOperand(1));
7077 TmpInst.addOperand(Inst.getOperand(3));
7078 TmpInst.addOperand(Inst.getOperand(4));
7079 TmpInst.addOperand(Inst.getOperand(5));
7080 Inst = TmpInst;
7081 return true;
7082 }
7083 return false;
7084 }
Jim Grosbach12ccf452011-12-22 18:04:04 +00007085 case ARM::ANDrsi:
7086 case ARM::ORRrsi:
7087 case ARM::EORrsi:
7088 case ARM::BICrsi:
7089 case ARM::SUBrsi:
7090 case ARM::ADDrsi: {
7091 unsigned newOpc;
7092 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7093 if (SOpc == ARM_AM::rrx) return false;
7094 switch (Inst.getOpcode()) {
Craig Toppere55c5562012-02-07 02:50:20 +00007095 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach12ccf452011-12-22 18:04:04 +00007096 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7097 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7098 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7099 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7100 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7101 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7102 }
7103 // If the shift is by zero, use the non-shifted instruction definition.
7104 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7105 MCInst TmpInst;
7106 TmpInst.setOpcode(newOpc);
7107 TmpInst.addOperand(Inst.getOperand(0));
7108 TmpInst.addOperand(Inst.getOperand(1));
7109 TmpInst.addOperand(Inst.getOperand(2));
7110 TmpInst.addOperand(Inst.getOperand(4));
7111 TmpInst.addOperand(Inst.getOperand(5));
7112 TmpInst.addOperand(Inst.getOperand(6));
7113 Inst = TmpInst;
7114 return true;
7115 }
7116 return false;
7117 }
Jim Grosbach82f76d12012-01-25 19:52:01 +00007118 case ARM::ITasm:
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007119 case ARM::t2IT: {
7120 // The mask bits for all but the first condition are represented as
7121 // the low bit of the condition code value implies 't'. We currently
7122 // always have 1 implies 't', so XOR toggle the bits if the low bit
7123 // of the condition code is zero. The encoding also expects the low
7124 // bit of the condition to be encoded as bit 4 of the mask operand,
7125 // so mask that in if needed
7126 MCOperand &MO = Inst.getOperand(1);
7127 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00007128 unsigned OrigMask = Mask;
7129 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007130 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007131 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7132 for (unsigned i = 3; i != TZ; --i)
7133 Mask ^= 1 << i;
7134 } else
7135 Mask |= 0x10;
7136 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00007137
7138 // Set up the IT block state according to the IT instruction we just
7139 // matched.
7140 assert(!inITBlock() && "nested IT blocks?!");
7141 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7142 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7143 ITState.CurPosition = 0;
7144 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007145 break;
7146 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007147 }
Jim Grosbachafad0532011-11-10 23:42:14 +00007148 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007149}
7150
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007151unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7152 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7153 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007154 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00007155 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007156 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7157 assert(MCID.hasOptionalDef() &&
7158 "optionally flag setting instruction missing optional def operand");
7159 assert(MCID.NumOperands == Inst.getNumOperands() &&
7160 "operand count mismatch!");
7161 // Find the optional-def operand (cc_out).
7162 unsigned OpNo;
7163 for (OpNo = 0;
7164 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7165 ++OpNo)
7166 ;
7167 // If we're parsing Thumb1, reject it completely.
7168 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7169 return Match_MnemonicFail;
7170 // If we're parsing Thumb2, which form is legal depends on whether we're
7171 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00007172 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7173 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007174 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00007175 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7176 inITBlock())
7177 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007178 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007179 // Some high-register supporting Thumb1 encodings only allow both registers
7180 // to be from r0-r7 when in Thumb2.
7181 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7182 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7183 isARMLowRegister(Inst.getOperand(2).getReg()))
7184 return Match_RequiresThumb2;
7185 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00007186 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007187 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7188 isARMLowRegister(Inst.getOperand(1).getReg()))
7189 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007190 return Match_Success;
7191}
7192
Chris Lattner9487de62010-10-28 21:28:01 +00007193bool ARMAsmParser::
7194MatchAndEmitInstruction(SMLoc IDLoc,
7195 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7196 MCStreamer &Out) {
7197 MCInst Inst;
7198 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00007199 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00007200 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00007201 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00007202 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007203 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007204 // Context sensitive operand constraints aren't handled by the matcher,
7205 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007206 if (validateInstruction(Inst, Operands)) {
7207 // Still progress the IT block, otherwise one wrong condition causes
7208 // nasty cascading errors.
7209 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007210 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007211 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007212
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007213 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00007214 // encoding is selected. Loop on it while changes happen so the
7215 // individual transformations can chain off each other. E.g.,
7216 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7217 while (processInstruction(Inst, Operands))
7218 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007219
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007220 // Only move forward at the very end so that everything in validate
7221 // and process gets a consistent answer about whether we're in an IT
7222 // block.
7223 forwardITPosition();
7224
Jim Grosbach82f76d12012-01-25 19:52:01 +00007225 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7226 // doesn't actually encode.
7227 if (Inst.getOpcode() == ARM::ITasm)
7228 return false;
7229
Jim Grosbach5e5eabb2012-01-26 23:20:15 +00007230 Inst.setLoc(IDLoc);
Chris Lattner9487de62010-10-28 21:28:01 +00007231 Out.EmitInstruction(Inst);
7232 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007233 case Match_MissingFeature:
7234 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7235 return true;
7236 case Match_InvalidOperand: {
7237 SMLoc ErrorLoc = IDLoc;
7238 if (ErrorInfo != ~0U) {
7239 if (ErrorInfo >= Operands.size())
7240 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00007241
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007242 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7243 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7244 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00007245
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007246 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00007247 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007248 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007249 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00007250 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00007251 // The converter function will have already emited a diagnostic.
7252 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00007253 case Match_RequiresNotITBlock:
7254 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007255 case Match_RequiresITBlock:
7256 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007257 case Match_RequiresV6:
7258 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7259 case Match_RequiresThumb2:
7260 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007261 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00007262
Eric Christopher91d7b902010-10-29 09:26:59 +00007263 llvm_unreachable("Implement any new match types added!");
Chris Lattner9487de62010-10-28 21:28:01 +00007264}
7265
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007266/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00007267bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7268 StringRef IDVal = DirectiveID.getIdentifier();
7269 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007270 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007271 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007272 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00007273 else if (IDVal == ".arm")
7274 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007275 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007276 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007277 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007278 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007279 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007280 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00007281 else if (IDVal == ".unreq")
7282 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kim135d2442011-12-20 17:38:12 +00007283 else if (IDVal == ".arch")
7284 return parseDirectiveArch(DirectiveID.getLoc());
7285 else if (IDVal == ".eabi_attribute")
7286 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00007287 return true;
7288}
7289
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007290/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00007291/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007292bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00007293 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7294 for (;;) {
7295 const MCExpr *Value;
7296 if (getParser().ParseExpression(Value))
7297 return true;
7298
Chris Lattnerc35681b2010-01-19 19:46:13 +00007299 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00007300
7301 if (getLexer().is(AsmToken::EndOfStatement))
7302 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00007303
Kevin Enderbyccab3172009-09-15 00:27:25 +00007304 // FIXME: Improve diagnostic.
7305 if (getLexer().isNot(AsmToken::Comma))
7306 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007307 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007308 }
7309 }
7310
Sean Callanana83fd7d2010-01-19 20:27:46 +00007311 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007312 return false;
7313}
7314
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007315/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00007316/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007317bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00007318 if (getLexer().isNot(AsmToken::EndOfStatement))
7319 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007320 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007321
Jim Grosbach7f882392011-12-07 18:04:19 +00007322 if (!isThumb())
7323 SwitchMode();
7324 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7325 return false;
7326}
7327
7328/// parseDirectiveARM
7329/// ::= .arm
7330bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7331 if (getLexer().isNot(AsmToken::EndOfStatement))
7332 return Error(L, "unexpected token in directive");
7333 Parser.Lex();
7334
7335 if (isThumb())
7336 SwitchMode();
7337 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00007338 return false;
7339}
7340
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007341/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00007342/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007343bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007344 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7345 bool isMachO = MAI.hasSubsectionsViaSymbols();
7346 StringRef Name;
Jim Grosbach1152cc02011-12-21 22:30:16 +00007347 bool needFuncName = true;
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007348
Jim Grosbach1152cc02011-12-21 22:30:16 +00007349 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007350 // ELF doesn't
7351 if (isMachO) {
7352 const AsmToken &Tok = Parser.getTok();
Jim Grosbach1152cc02011-12-21 22:30:16 +00007353 if (Tok.isNot(AsmToken::EndOfStatement)) {
7354 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7355 return Error(L, "unexpected token in .thumb_func directive");
7356 Name = Tok.getIdentifier();
7357 Parser.Lex(); // Consume the identifier token.
7358 needFuncName = false;
7359 }
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007360 }
7361
Jim Grosbach1152cc02011-12-21 22:30:16 +00007362 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00007363 return Error(L, "unexpected token in directive");
Jim Grosbach1152cc02011-12-21 22:30:16 +00007364
7365 // Eat the end of statement and any blank lines that follow.
7366 while (getLexer().is(AsmToken::EndOfStatement))
7367 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007368
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007369 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbach1152cc02011-12-21 22:30:16 +00007370 // We really should be checking the next symbol definition even if there's
7371 // stuff in between.
7372 if (needFuncName) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00007373 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007374 }
7375
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00007376 // Mark symbol as a thumb symbol.
7377 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7378 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00007379 return false;
7380}
7381
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007382/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00007383/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007384bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00007385 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007386 if (Tok.isNot(AsmToken::Identifier))
7387 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00007388 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00007389 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00007390 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00007391 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00007392 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00007393 else
7394 return Error(L, "unrecognized syntax mode in .syntax directive");
7395
7396 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00007397 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007398 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007399
7400 // TODO tell the MC streamer the mode
7401 // getParser().getStreamer().Emit???();
7402 return false;
7403}
7404
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007405/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00007406/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007407bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00007408 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007409 if (Tok.isNot(AsmToken::Integer))
7410 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00007411 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00007412 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00007413 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00007414 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00007415 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007416 else
7417 return Error(L, "invalid operand to .code directive");
7418
7419 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00007420 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007421 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007422
Evan Cheng284b4672011-07-08 22:36:29 +00007423 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00007424 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00007425 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00007426 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00007427 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00007428 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00007429 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00007430 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00007431 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00007432
Kevin Enderby146dcf22009-10-15 20:48:48 +00007433 return false;
7434}
7435
Jim Grosbachab5830e2011-12-14 02:16:11 +00007436/// parseDirectiveReq
7437/// ::= name .req registername
7438bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7439 Parser.Lex(); // Eat the '.req' token.
7440 unsigned Reg;
7441 SMLoc SRegLoc, ERegLoc;
7442 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7443 Parser.EatToEndOfStatement();
7444 return Error(SRegLoc, "register name expected");
7445 }
7446
7447 // Shouldn't be anything else.
7448 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7449 Parser.EatToEndOfStatement();
7450 return Error(Parser.getTok().getLoc(),
7451 "unexpected input in .req directive.");
7452 }
7453
7454 Parser.Lex(); // Consume the EndOfStatement
7455
7456 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7457 return Error(SRegLoc, "redefinition of '" + Name +
7458 "' does not match original.");
7459
7460 return false;
7461}
7462
7463/// parseDirectiveUneq
7464/// ::= .unreq registername
7465bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7466 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7467 Parser.EatToEndOfStatement();
7468 return Error(L, "unexpected input in .unreq directive.");
7469 }
7470 RegisterReqs.erase(Parser.getTok().getIdentifier());
7471 Parser.Lex(); // Eat the identifier.
7472 return false;
7473}
7474
Jason W Kim135d2442011-12-20 17:38:12 +00007475/// parseDirectiveArch
7476/// ::= .arch token
7477bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7478 return true;
7479}
7480
7481/// parseDirectiveEabiAttr
7482/// ::= .eabi_attribute int, int
7483bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7484 return true;
7485}
7486
Sean Callanan643a5572010-04-07 20:29:34 +00007487extern "C" void LLVMInitializeARMAsmLexer();
7488
Kevin Enderby8be42bd2009-10-30 22:55:57 +00007489/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00007490extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00007491 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7492 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00007493 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007494}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00007495
Chris Lattner3e4582a2010-09-06 19:11:01 +00007496#define GET_REGISTER_MATCHER
7497#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00007498#include "ARMGenAsmMatcher.inc"