blob: 29a9b0d844a3428dd694a3e8fc8926494a8535d5 [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();
785 return ARM_AM::getSOImmVal(-Value) != -1;
786 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000787 bool isT2SOImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000788 if (!isImm()) return false;
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000789 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
790 if (!CE) return false;
791 int64_t Value = CE->getValue();
792 return ARM_AM::getT2SOImmVal(Value) != -1;
793 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000794 bool isT2SOImmNot() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000795 if (!isImm()) return false;
Jim Grosbachb009a872011-10-28 22:36:30 +0000796 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
797 if (!CE) return false;
798 int64_t Value = CE->getValue();
799 return ARM_AM::getT2SOImmVal(~Value) != -1;
800 }
Jim Grosbach30506252011-12-08 00:31:07 +0000801 bool isT2SOImmNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000802 if (!isImm()) return false;
Jim Grosbach30506252011-12-08 00:31:07 +0000803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
804 if (!CE) return false;
805 int64_t Value = CE->getValue();
806 return ARM_AM::getT2SOImmVal(-Value) != -1;
807 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000808 bool isSetEndImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000809 if (!isImm()) return false;
Jim Grosbach0a547702011-07-22 17:44:50 +0000810 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
811 if (!CE) return false;
812 int64_t Value = CE->getValue();
813 return Value == 1 || Value == 0;
814 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000815 bool isReg() const { return Kind == k_Register; }
816 bool isRegList() const { return Kind == k_RegisterList; }
817 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
818 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
819 bool isToken() const { return Kind == k_Token; }
820 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
821 bool isMemory() const { return Kind == k_Memory; }
822 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
823 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
824 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
825 bool isRotImm() const { return Kind == k_RotateImmediate; }
826 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
827 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000828 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000829 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000830 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000831 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000832 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000833 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000834 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000835 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
836 (alignOK || Memory.Alignment == 0);
837 }
Jim Grosbach94298a92012-01-18 22:46:46 +0000838 bool isMemPCRelImm12() const {
839 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
840 return false;
841 // Base register must be PC.
842 if (Memory.BaseRegNum != ARM::PC)
843 return false;
844 // Immediate offset in range [-4095, 4095].
845 if (!Memory.OffsetImm) return true;
846 int64_t Val = Memory.OffsetImm->getValue();
847 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
848 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000849 bool isAlignedMemory() const {
850 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000851 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000852 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000853 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000854 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000855 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000856 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000857 if (!Memory.OffsetImm) return true;
858 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000859 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000860 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000861 bool isAM2OffsetImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000862 if (!isImm()) return false;
Jim Grosbachcd17c122011-08-04 23:01:30 +0000863 // Immediate offset in range [-4095, 4095].
864 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
865 if (!CE) return false;
866 int64_t Val = CE->getValue();
867 return Val > -4096 && Val < 4096;
868 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000869 bool isAddrMode3() const {
Jim Grosbach8648c102011-12-19 23:06:24 +0000870 // If we have an immediate that's not a constant, treat it as a label
871 // reference needing a fixup. If it is a constant, it's something else
872 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000873 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +0000874 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000875 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000876 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000877 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000878 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000879 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000880 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000881 if (!Memory.OffsetImm) return true;
882 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000883 return Val > -256 && Val < 256;
884 }
885 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000886 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000887 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000888 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000889 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
890 // Immediate offset in range [-255, 255].
891 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
892 if (!CE) return false;
893 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000894 // Special case, #-0 is INT32_MIN.
895 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000896 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000897 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000898 // If we have an immediate that's not a constant, treat it as a label
899 // reference needing a fixup. If it is a constant, it's something else
900 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000901 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000902 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000903 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000904 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000905 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000906 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000907 if (!Memory.OffsetImm) return true;
908 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000909 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000910 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000911 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000912 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000913 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000914 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000915 return false;
916 return true;
917 }
918 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000919 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000920 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
921 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000922 return false;
923 return true;
924 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000925 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000926 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000927 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000928 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000929 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000930 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000931 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
932 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000933 return false;
934 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000935 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000936 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000937 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000938 return false;
939 return true;
940 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000941 bool isMemThumbRR() const {
942 // Thumb reg+reg addressing is simple. Just two registers, a base and
943 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000944 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000945 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000946 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000947 return isARMLowRegister(Memory.BaseRegNum) &&
948 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000949 }
950 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000951 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000952 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000953 return false;
954 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000955 if (!Memory.OffsetImm) return true;
956 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000957 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
958 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000959 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000960 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000961 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000962 return false;
963 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000964 if (!Memory.OffsetImm) return true;
965 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000966 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
967 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000968 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000969 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000970 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000971 return false;
972 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000973 if (!Memory.OffsetImm) return true;
974 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000975 return Val >= 0 && Val <= 31;
976 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000977 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000978 if (!isMemory() || Memory.OffsetRegNum != 0 ||
979 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000980 return false;
981 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000982 if (!Memory.OffsetImm) return true;
983 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000984 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000985 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000986 bool isMemImm8s4Offset() const {
Jim Grosbach8648c102011-12-19 23:06:24 +0000987 // If we have an immediate that's not a constant, treat it as a label
988 // reference needing a fixup. If it is a constant, it's something else
989 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000990 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +0000991 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000992 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000993 return false;
994 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000995 if (!Memory.OffsetImm) return true;
996 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000997 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
998 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000999 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001000 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +00001001 return false;
1002 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001003 if (!Memory.OffsetImm) return true;
1004 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001005 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1006 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001007 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001008 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001009 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001010 // Base reg of PC isn't allowed for these encodings.
1011 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001012 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001013 if (!Memory.OffsetImm) return true;
1014 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001015 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001016 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001017 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001018 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001019 return false;
1020 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001021 if (!Memory.OffsetImm) return true;
1022 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001023 return Val >= 0 && Val < 256;
1024 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001025 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001026 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001027 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001028 // Base reg of PC isn't allowed for these encodings.
1029 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001030 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001031 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001032 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001033 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001034 }
1035 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001036 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001037 return false;
1038 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001039 if (!Memory.OffsetImm) return true;
1040 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001041 return (Val >= 0 && Val < 4096);
1042 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001043 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001044 // If we have an immediate that's not a constant, treat it as a label
1045 // reference needing a fixup. If it is a constant, it's something else
1046 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001047 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001048 return true;
1049
Jim Grosbacha95ec992011-10-11 17:29:55 +00001050 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001051 return false;
1052 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001053 if (!Memory.OffsetImm) return true;
1054 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001055 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001056 }
1057 bool isPostIdxImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001058 if (!isImm()) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1060 if (!CE) return false;
1061 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001062 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001063 }
Jim Grosbach93981412011-10-11 21:55:36 +00001064 bool isPostIdxImm8s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001065 if (!isImm()) return false;
Jim Grosbach93981412011-10-11 21:55:36 +00001066 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1067 if (!CE) return false;
1068 int64_t Val = CE->getValue();
1069 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1070 (Val == INT32_MIN);
1071 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001072
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001073 bool isMSRMask() const { return Kind == k_MSRMask; }
1074 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001075
Jim Grosbach741cd732011-10-17 22:26:03 +00001076 // NEON operands.
Jim Grosbach2f50e922011-12-15 21:44:33 +00001077 bool isSingleSpacedVectorList() const {
1078 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1079 }
1080 bool isDoubleSpacedVectorList() const {
1081 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1082 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001083 bool isVecListOneD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001084 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001085 return VectorList.Count == 1;
1086 }
1087
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001088 bool isVecListDPair() const {
1089 if (!isSingleSpacedVectorList()) return false;
1090 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1091 .contains(VectorList.RegNum));
1092 }
1093
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001094 bool isVecListThreeD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001096 return VectorList.Count == 3;
1097 }
1098
Jim Grosbach846bcff2011-10-21 20:35:01 +00001099 bool isVecListFourD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001100 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach846bcff2011-10-21 20:35:01 +00001101 return VectorList.Count == 4;
1102 }
1103
Jim Grosbache5307f92012-03-05 21:43:40 +00001104 bool isVecListDPairSpaced() const {
1105 if (!isSingleSpacedVectorList()) return false;
1106 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1107 .contains(VectorList.RegNum));
1108 }
1109
Jim Grosbachac2af3f2012-01-23 23:20:46 +00001110 bool isVecListThreeQ() const {
1111 if (!isDoubleSpacedVectorList()) return false;
1112 return VectorList.Count == 3;
1113 }
1114
Jim Grosbach1e946a42012-01-24 00:43:12 +00001115 bool isVecListFourQ() const {
1116 if (!isDoubleSpacedVectorList()) return false;
1117 return VectorList.Count == 4;
1118 }
1119
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001120 bool isSingleSpacedVectorAllLanes() const {
1121 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1122 }
1123 bool isDoubleSpacedVectorAllLanes() const {
1124 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1125 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001126 bool isVecListOneDAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001127 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001128 return VectorList.Count == 1;
1129 }
1130
Jim Grosbach13a292c2012-03-06 22:01:44 +00001131 bool isVecListDPairAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001132 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach13a292c2012-03-06 22:01:44 +00001133 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1134 .contains(VectorList.RegNum));
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001135 }
1136
Jim Grosbached428bc2012-03-06 23:10:38 +00001137 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001138 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001139 return VectorList.Count == 2;
1140 }
1141
Jim Grosbachb78403c2012-01-24 23:47:04 +00001142 bool isVecListThreeDAllLanes() const {
1143 if (!isSingleSpacedVectorAllLanes()) return false;
1144 return VectorList.Count == 3;
1145 }
1146
1147 bool isVecListThreeQAllLanes() const {
1148 if (!isDoubleSpacedVectorAllLanes()) return false;
1149 return VectorList.Count == 3;
1150 }
1151
Jim Grosbach086cbfa2012-01-25 00:01:08 +00001152 bool isVecListFourDAllLanes() const {
1153 if (!isSingleSpacedVectorAllLanes()) return false;
1154 return VectorList.Count == 4;
1155 }
1156
1157 bool isVecListFourQAllLanes() const {
1158 if (!isDoubleSpacedVectorAllLanes()) return false;
1159 return VectorList.Count == 4;
1160 }
1161
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001162 bool isSingleSpacedVectorIndexed() const {
1163 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1164 }
1165 bool isDoubleSpacedVectorIndexed() const {
1166 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1167 }
Jim Grosbach04945c42011-12-02 00:35:16 +00001168 bool isVecListOneDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001169 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach04945c42011-12-02 00:35:16 +00001170 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1171 }
1172
Jim Grosbachda511042011-12-14 23:35:06 +00001173 bool isVecListOneDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001174 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001175 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1176 }
1177
1178 bool isVecListOneDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001179 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001180 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1181 }
1182
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001183 bool isVecListTwoDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001184 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001185 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1186 }
1187
Jim Grosbachda511042011-12-14 23:35:06 +00001188 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001189 if (!isSingleSpacedVectorIndexed()) return false;
1190 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1191 }
1192
1193 bool isVecListTwoQWordIndexed() const {
1194 if (!isDoubleSpacedVectorIndexed()) return false;
1195 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1196 }
1197
1198 bool isVecListTwoQHWordIndexed() const {
1199 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001200 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1201 }
1202
1203 bool isVecListTwoDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001204 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001205 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1206 }
1207
Jim Grosbacha8b444b2012-01-23 21:53:26 +00001208 bool isVecListThreeDByteIndexed() const {
1209 if (!isSingleSpacedVectorIndexed()) return false;
1210 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1211 }
1212
1213 bool isVecListThreeDHWordIndexed() const {
1214 if (!isSingleSpacedVectorIndexed()) return false;
1215 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1216 }
1217
1218 bool isVecListThreeQWordIndexed() const {
1219 if (!isDoubleSpacedVectorIndexed()) return false;
1220 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1221 }
1222
1223 bool isVecListThreeQHWordIndexed() const {
1224 if (!isDoubleSpacedVectorIndexed()) return false;
1225 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1226 }
1227
1228 bool isVecListThreeDWordIndexed() const {
1229 if (!isSingleSpacedVectorIndexed()) return false;
1230 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1231 }
1232
Jim Grosbach14952a02012-01-24 18:37:25 +00001233 bool isVecListFourDByteIndexed() const {
1234 if (!isSingleSpacedVectorIndexed()) return false;
1235 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1236 }
1237
1238 bool isVecListFourDHWordIndexed() const {
1239 if (!isSingleSpacedVectorIndexed()) return false;
1240 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1241 }
1242
1243 bool isVecListFourQWordIndexed() const {
1244 if (!isDoubleSpacedVectorIndexed()) return false;
1245 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1246 }
1247
1248 bool isVecListFourQHWordIndexed() const {
1249 if (!isDoubleSpacedVectorIndexed()) return false;
1250 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1251 }
1252
1253 bool isVecListFourDWordIndexed() const {
1254 if (!isSingleSpacedVectorIndexed()) return false;
1255 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1256 }
1257
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001258 bool isVectorIndex8() const {
1259 if (Kind != k_VectorIndex) return false;
1260 return VectorIndex.Val < 8;
1261 }
1262 bool isVectorIndex16() const {
1263 if (Kind != k_VectorIndex) return false;
1264 return VectorIndex.Val < 4;
1265 }
1266 bool isVectorIndex32() const {
1267 if (Kind != k_VectorIndex) return false;
1268 return VectorIndex.Val < 2;
1269 }
1270
Jim Grosbach741cd732011-10-17 22:26:03 +00001271 bool isNEONi8splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001272 if (!isImm()) return false;
Jim Grosbach741cd732011-10-17 22:26:03 +00001273 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1274 // Must be a constant.
1275 if (!CE) return false;
1276 int64_t Value = CE->getValue();
1277 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1278 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001279 return Value >= 0 && Value < 256;
1280 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001281
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001282 bool isNEONi16splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001283 if (!isImm()) return false;
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001284 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1285 // Must be a constant.
1286 if (!CE) return false;
1287 int64_t Value = CE->getValue();
1288 // i16 value in the range [0,255] or [0x0100, 0xff00]
1289 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1290 }
1291
Jim Grosbach8211c052011-10-18 00:22:00 +00001292 bool isNEONi32splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001293 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001294 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1295 // Must be a constant.
1296 if (!CE) return false;
1297 int64_t Value = CE->getValue();
1298 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1299 return (Value >= 0 && Value < 256) ||
1300 (Value >= 0x0100 && Value <= 0xff00) ||
1301 (Value >= 0x010000 && Value <= 0xff0000) ||
1302 (Value >= 0x01000000 && Value <= 0xff000000);
1303 }
1304
1305 bool isNEONi32vmov() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001306 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001307 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1308 // Must be a constant.
1309 if (!CE) return false;
1310 int64_t Value = CE->getValue();
1311 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1312 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1313 return (Value >= 0 && Value < 256) ||
1314 (Value >= 0x0100 && Value <= 0xff00) ||
1315 (Value >= 0x010000 && Value <= 0xff0000) ||
1316 (Value >= 0x01000000 && Value <= 0xff000000) ||
1317 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1318 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1319 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00001320 bool isNEONi32vmovNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001321 if (!isImm()) return false;
Jim Grosbach045b6c72011-12-19 23:51:07 +00001322 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1323 // Must be a constant.
1324 if (!CE) return false;
1325 int64_t Value = ~CE->getValue();
1326 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1327 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1328 return (Value >= 0 && Value < 256) ||
1329 (Value >= 0x0100 && Value <= 0xff00) ||
1330 (Value >= 0x010000 && Value <= 0xff0000) ||
1331 (Value >= 0x01000000 && Value <= 0xff000000) ||
1332 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1333 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1334 }
Jim Grosbach8211c052011-10-18 00:22:00 +00001335
Jim Grosbache4454e02011-10-18 16:18:11 +00001336 bool isNEONi64splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001337 if (!isImm()) return false;
Jim Grosbache4454e02011-10-18 16:18:11 +00001338 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1339 // Must be a constant.
1340 if (!CE) return false;
1341 uint64_t Value = CE->getValue();
1342 // i64 value with each byte being either 0 or 0xff.
1343 for (unsigned i = 0; i < 8; ++i)
1344 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1345 return true;
1346 }
1347
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001348 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001349 // Add as immediates when possible. Null MCExpr = 0.
1350 if (Expr == 0)
1351 Inst.addOperand(MCOperand::CreateImm(0));
1352 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001353 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1354 else
1355 Inst.addOperand(MCOperand::CreateExpr(Expr));
1356 }
1357
Daniel Dunbard8042b72010-08-11 06:36:53 +00001358 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001359 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001360 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001361 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1362 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001363 }
1364
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001365 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1366 assert(N == 1 && "Invalid number of operands!");
1367 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1368 }
1369
Jim Grosbach48399582011-10-12 17:34:41 +00001370 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
1372 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1373 }
1374
1375 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1376 assert(N == 1 && "Invalid number of operands!");
1377 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1378 }
1379
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001380 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
1382 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1383 }
1384
1385 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1388 }
1389
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001390 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
1392 Inst.addOperand(MCOperand::CreateReg(getReg()));
1393 }
1394
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001395 void addRegOperands(MCInst &Inst, unsigned N) const {
1396 assert(N == 1 && "Invalid number of operands!");
1397 Inst.addOperand(MCOperand::CreateReg(getReg()));
1398 }
1399
Jim Grosbachac798e12011-07-25 20:49:51 +00001400 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001401 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001402 assert(isRegShiftedReg() &&
1403 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001404 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1405 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001406 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001407 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001408 }
1409
Jim Grosbachac798e12011-07-25 20:49:51 +00001410 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001411 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001412 assert(isRegShiftedImm() &&
1413 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001414 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001415 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001416 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001417 }
1418
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001419 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001420 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001421 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1422 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001423 }
1424
Bill Wendling8d2aa032010-11-08 23:49:57 +00001425 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001426 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001427 const SmallVectorImpl<unsigned> &RegList = getRegList();
1428 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001429 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1430 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001431 }
1432
Bill Wendling9898ac92010-11-17 04:32:08 +00001433 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1434 addRegListOperands(Inst, N);
1435 }
1436
1437 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1438 addRegListOperands(Inst, N);
1439 }
1440
Jim Grosbach833b9d32011-07-27 20:15:40 +00001441 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1444 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1445 }
1446
Jim Grosbach864b6092011-07-28 21:34:26 +00001447 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1448 assert(N == 1 && "Invalid number of operands!");
1449 // Munge the lsb/width into a bitfield mask.
1450 unsigned lsb = Bitfield.LSB;
1451 unsigned width = Bitfield.Width;
1452 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1453 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1454 (32 - (lsb + width)));
1455 Inst.addOperand(MCOperand::CreateImm(Mask));
1456 }
1457
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001458 void addImmOperands(MCInst &Inst, unsigned N) const {
1459 assert(N == 1 && "Invalid number of operands!");
1460 addExpr(Inst, getImm());
1461 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001462
Jim Grosbachea231912011-12-22 22:19:05 +00001463 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1464 assert(N == 1 && "Invalid number of operands!");
1465 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1466 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1467 }
1468
1469 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1470 assert(N == 1 && "Invalid number of operands!");
1471 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1472 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1473 }
1474
Jim Grosbache7fbce72011-10-03 23:38:36 +00001475 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00001477 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1478 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1479 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbache7fbce72011-10-03 23:38:36 +00001480 }
1481
Jim Grosbach7db8d692011-09-08 22:07:06 +00001482 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
1484 // FIXME: We really want to scale the value here, but the LDRD/STRD
1485 // instruction don't encode operands that way yet.
1486 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1487 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1488 }
1489
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001490 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1491 assert(N == 1 && "Invalid number of operands!");
1492 // The immediate is scaled by four in the encoding and is stored
1493 // in the MCInst as such. Lop off the low two bits here.
1494 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1495 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1496 }
1497
1498 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1499 assert(N == 1 && "Invalid number of operands!");
1500 // The immediate is scaled by four in the encoding and is stored
1501 // in the MCInst as such. Lop off the low two bits here.
1502 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1503 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1504 }
1505
Jim Grosbach475c6db2011-07-25 23:09:14 +00001506 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 // The constant encodes as the immediate-1, and we store in the instruction
1509 // the bits as encoded, so subtract off one here.
1510 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1511 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1512 }
1513
Jim Grosbach801e0a32011-07-22 23:16:18 +00001514 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1515 assert(N == 1 && "Invalid number of operands!");
1516 // The constant encodes as the immediate-1, and we store in the instruction
1517 // the bits as encoded, so subtract off one here.
1518 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1519 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1520 }
1521
Jim Grosbach46dd4132011-08-17 21:51:27 +00001522 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524 // The constant encodes as the immediate, except for 32, which encodes as
1525 // zero.
1526 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1527 unsigned Imm = CE->getValue();
1528 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1529 }
1530
Jim Grosbach27c1e252011-07-21 17:23:04 +00001531 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1534 // the instruction as well.
1535 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1536 int Val = CE->getValue();
1537 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1538 }
1539
Jim Grosbachb009a872011-10-28 22:36:30 +00001540 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 // The operand is actually a t2_so_imm, but we have its bitwise
1543 // negation in the assembly source, so twiddle it here.
1544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1545 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1546 }
1547
Jim Grosbach30506252011-12-08 00:31:07 +00001548 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1549 assert(N == 1 && "Invalid number of operands!");
1550 // The operand is actually a t2_so_imm, but we have its
1551 // negation in the assembly source, so twiddle it here.
1552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1553 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1554 }
1555
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001556 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1557 assert(N == 1 && "Invalid number of operands!");
1558 // The operand is actually a so_imm, but we have its bitwise
1559 // negation in the assembly source, so twiddle it here.
1560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1561 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1562 }
1563
Jim Grosbach30506252011-12-08 00:31:07 +00001564 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566 // The operand is actually a so_imm, but we have its
1567 // negation in the assembly source, so twiddle it here.
1568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1569 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1570 }
1571
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001572 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1573 assert(N == 1 && "Invalid number of operands!");
1574 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1575 }
1576
Jim Grosbachd3595712011-08-03 23:50:40 +00001577 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001579 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001580 }
1581
Jim Grosbach94298a92012-01-18 22:46:46 +00001582 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
1584 int32_t Imm = Memory.OffsetImm->getValue();
1585 // FIXME: Handle #-0
1586 if (Imm == INT32_MIN) Imm = 0;
1587 Inst.addOperand(MCOperand::CreateImm(Imm));
1588 }
1589
Jim Grosbacha95ec992011-10-11 17:29:55 +00001590 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1591 assert(N == 2 && "Invalid number of operands!");
1592 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1593 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1594 }
1595
Jim Grosbachd3595712011-08-03 23:50:40 +00001596 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1597 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001598 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1599 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001600 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1601 // Special case for #-0
1602 if (Val == INT32_MIN) Val = 0;
1603 if (Val < 0) Val = -Val;
1604 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1605 } else {
1606 // For register offset, we encode the shift type and negation flag
1607 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001608 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1609 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001610 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001611 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1612 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001613 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001614 }
1615
Jim Grosbachcd17c122011-08-04 23:01:30 +00001616 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1617 assert(N == 2 && "Invalid number of operands!");
1618 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1619 assert(CE && "non-constant AM2OffsetImm operand!");
1620 int32_t Val = CE->getValue();
1621 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1622 // Special case for #-0
1623 if (Val == INT32_MIN) Val = 0;
1624 if (Val < 0) Val = -Val;
1625 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1626 Inst.addOperand(MCOperand::CreateReg(0));
1627 Inst.addOperand(MCOperand::CreateImm(Val));
1628 }
1629
Jim Grosbach5b96b802011-08-10 20:29:19 +00001630 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1631 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001632 // If we have an immediate that's not a constant, treat it as a label
1633 // reference needing a fixup. If it is a constant, it's something else
1634 // and we reject it.
1635 if (isImm()) {
1636 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1637 Inst.addOperand(MCOperand::CreateReg(0));
1638 Inst.addOperand(MCOperand::CreateImm(0));
1639 return;
1640 }
1641
Jim Grosbach871dff72011-10-11 15:59:20 +00001642 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1643 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001644 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1645 // Special case for #-0
1646 if (Val == INT32_MIN) Val = 0;
1647 if (Val < 0) Val = -Val;
1648 Val = ARM_AM::getAM3Opc(AddSub, Val);
1649 } else {
1650 // For register offset, we encode the shift type and negation flag
1651 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001652 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001653 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001654 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1655 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001656 Inst.addOperand(MCOperand::CreateImm(Val));
1657 }
1658
1659 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1660 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001661 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001662 int32_t Val =
1663 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1664 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1665 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001666 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001667 }
1668
1669 // Constant offset.
1670 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1671 int32_t Val = CE->getValue();
1672 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1673 // Special case for #-0
1674 if (Val == INT32_MIN) Val = 0;
1675 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001676 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001677 Inst.addOperand(MCOperand::CreateReg(0));
1678 Inst.addOperand(MCOperand::CreateImm(Val));
1679 }
1680
Jim Grosbachd3595712011-08-03 23:50:40 +00001681 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1682 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001683 // If we have an immediate that's not a constant, treat it as a label
1684 // reference needing a fixup. If it is a constant, it's something else
1685 // and we reject it.
1686 if (isImm()) {
1687 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1688 Inst.addOperand(MCOperand::CreateImm(0));
1689 return;
1690 }
1691
Jim Grosbachd3595712011-08-03 23:50:40 +00001692 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001693 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001694 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1695 // Special case for #-0
1696 if (Val == INT32_MIN) Val = 0;
1697 if (Val < 0) Val = -Val;
1698 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001699 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001700 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001701 }
1702
Jim Grosbach7db8d692011-09-08 22:07:06 +00001703 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1704 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001705 // If we have an immediate that's not a constant, treat it as a label
1706 // reference needing a fixup. If it is a constant, it's something else
1707 // and we reject it.
1708 if (isImm()) {
1709 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1710 Inst.addOperand(MCOperand::CreateImm(0));
1711 return;
1712 }
1713
Jim Grosbach871dff72011-10-11 15:59:20 +00001714 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1715 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001716 Inst.addOperand(MCOperand::CreateImm(Val));
1717 }
1718
Jim Grosbacha05627e2011-09-09 18:37:27 +00001719 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1720 assert(N == 2 && "Invalid number of operands!");
1721 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001722 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1723 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001724 Inst.addOperand(MCOperand::CreateImm(Val));
1725 }
1726
Jim Grosbachd3595712011-08-03 23:50:40 +00001727 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1728 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001729 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1730 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001731 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001732 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001733
Jim Grosbach2392c532011-09-07 23:39:14 +00001734 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1735 addMemImm8OffsetOperands(Inst, N);
1736 }
1737
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001738 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001739 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001740 }
1741
1742 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1743 assert(N == 2 && "Invalid number of operands!");
1744 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001745 if (isImm()) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001746 addExpr(Inst, getImm());
1747 Inst.addOperand(MCOperand::CreateImm(0));
1748 return;
1749 }
1750
1751 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001752 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1753 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001754 Inst.addOperand(MCOperand::CreateImm(Val));
1755 }
1756
Jim Grosbachd3595712011-08-03 23:50:40 +00001757 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1758 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001759 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001760 if (isImm()) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001761 addExpr(Inst, getImm());
1762 Inst.addOperand(MCOperand::CreateImm(0));
1763 return;
1764 }
1765
1766 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001767 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1768 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001769 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001770 }
Bill Wendling811c9362010-11-30 07:44:32 +00001771
Jim Grosbach05541f42011-09-19 22:21:13 +00001772 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1773 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001774 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1775 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001776 }
1777
1778 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1779 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001780 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1781 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001782 }
1783
Jim Grosbachd3595712011-08-03 23:50:40 +00001784 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1785 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001786 unsigned Val =
1787 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1788 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001789 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1790 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001791 Inst.addOperand(MCOperand::CreateImm(Val));
1792 }
1793
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001794 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1795 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001796 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1797 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1798 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001799 }
1800
Jim Grosbachd3595712011-08-03 23:50:40 +00001801 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1802 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001803 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1804 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001805 }
1806
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001807 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1808 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001809 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1810 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001811 Inst.addOperand(MCOperand::CreateImm(Val));
1812 }
1813
Jim Grosbach26d35872011-08-19 18:55:51 +00001814 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1815 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001816 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1817 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001818 Inst.addOperand(MCOperand::CreateImm(Val));
1819 }
1820
Jim Grosbacha32c7532011-08-19 18:49:59 +00001821 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1822 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001823 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1824 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001825 Inst.addOperand(MCOperand::CreateImm(Val));
1826 }
1827
Jim Grosbach23983d62011-08-19 18:13:48 +00001828 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1829 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001830 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1831 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001832 Inst.addOperand(MCOperand::CreateImm(Val));
1833 }
1834
Jim Grosbachd3595712011-08-03 23:50:40 +00001835 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1836 assert(N == 1 && "Invalid number of operands!");
1837 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1838 assert(CE && "non-constant post-idx-imm8 operand!");
1839 int Imm = CE->getValue();
1840 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001841 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001842 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1843 Inst.addOperand(MCOperand::CreateImm(Imm));
1844 }
1845
Jim Grosbach93981412011-10-11 21:55:36 +00001846 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1847 assert(N == 1 && "Invalid number of operands!");
1848 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1849 assert(CE && "non-constant post-idx-imm8s4 operand!");
1850 int Imm = CE->getValue();
1851 bool isAdd = Imm >= 0;
1852 if (Imm == INT32_MIN) Imm = 0;
1853 // Immediate is scaled by 4.
1854 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1855 Inst.addOperand(MCOperand::CreateImm(Imm));
1856 }
1857
Jim Grosbachd3595712011-08-03 23:50:40 +00001858 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1859 assert(N == 2 && "Invalid number of operands!");
1860 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001861 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1862 }
1863
1864 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1865 assert(N == 2 && "Invalid number of operands!");
1866 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1867 // The sign, shift type, and shift amount are encoded in a single operand
1868 // using the AM2 encoding helpers.
1869 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1870 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1871 PostIdxReg.ShiftTy);
1872 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001873 }
1874
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001875 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1876 assert(N == 1 && "Invalid number of operands!");
1877 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1878 }
1879
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001880 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1881 assert(N == 1 && "Invalid number of operands!");
1882 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1883 }
1884
Jim Grosbach182b6a02011-11-29 23:51:09 +00001885 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001886 assert(N == 1 && "Invalid number of operands!");
1887 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1888 }
1889
Jim Grosbach04945c42011-12-02 00:35:16 +00001890 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1891 assert(N == 2 && "Invalid number of operands!");
1892 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1893 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1894 }
1895
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001896 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1897 assert(N == 1 && "Invalid number of operands!");
1898 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1899 }
1900
1901 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1902 assert(N == 1 && "Invalid number of operands!");
1903 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1904 }
1905
1906 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1907 assert(N == 1 && "Invalid number of operands!");
1908 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1909 }
1910
Jim Grosbach741cd732011-10-17 22:26:03 +00001911 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1912 assert(N == 1 && "Invalid number of operands!");
1913 // The immediate encodes the type of constant as well as the value.
1914 // Mask in that this is an i8 splat.
1915 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1916 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1917 }
1918
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001919 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1920 assert(N == 1 && "Invalid number of operands!");
1921 // The immediate encodes the type of constant as well as the value.
1922 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1923 unsigned Value = CE->getValue();
1924 if (Value >= 256)
1925 Value = (Value >> 8) | 0xa00;
1926 else
1927 Value |= 0x800;
1928 Inst.addOperand(MCOperand::CreateImm(Value));
1929 }
1930
Jim Grosbach8211c052011-10-18 00:22:00 +00001931 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1932 assert(N == 1 && "Invalid number of operands!");
1933 // The immediate encodes the type of constant as well as the value.
1934 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1935 unsigned Value = CE->getValue();
1936 if (Value >= 256 && Value <= 0xff00)
1937 Value = (Value >> 8) | 0x200;
1938 else if (Value > 0xffff && Value <= 0xff0000)
1939 Value = (Value >> 16) | 0x400;
1940 else if (Value > 0xffffff)
1941 Value = (Value >> 24) | 0x600;
1942 Inst.addOperand(MCOperand::CreateImm(Value));
1943 }
1944
1945 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1946 assert(N == 1 && "Invalid number of operands!");
1947 // The immediate encodes the type of constant as well as the value.
1948 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1949 unsigned Value = CE->getValue();
1950 if (Value >= 256 && Value <= 0xffff)
1951 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1952 else if (Value > 0xffff && Value <= 0xffffff)
1953 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1954 else if (Value > 0xffffff)
1955 Value = (Value >> 24) | 0x600;
1956 Inst.addOperand(MCOperand::CreateImm(Value));
1957 }
1958
Jim Grosbach045b6c72011-12-19 23:51:07 +00001959 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1960 assert(N == 1 && "Invalid number of operands!");
1961 // The immediate encodes the type of constant as well as the value.
1962 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1963 unsigned Value = ~CE->getValue();
1964 if (Value >= 256 && Value <= 0xffff)
1965 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1966 else if (Value > 0xffff && Value <= 0xffffff)
1967 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1968 else if (Value > 0xffffff)
1969 Value = (Value >> 24) | 0x600;
1970 Inst.addOperand(MCOperand::CreateImm(Value));
1971 }
1972
Jim Grosbache4454e02011-10-18 16:18:11 +00001973 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1974 assert(N == 1 && "Invalid number of operands!");
1975 // The immediate encodes the type of constant as well as the value.
1976 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1977 uint64_t Value = CE->getValue();
1978 unsigned Imm = 0;
1979 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1980 Imm |= (Value & 1) << i;
1981 }
1982 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1983 }
1984
Jim Grosbach602aa902011-07-13 15:34:57 +00001985 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001986
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001987 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001988 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001989 Op->ITMask.Mask = Mask;
1990 Op->StartLoc = S;
1991 Op->EndLoc = S;
1992 return Op;
1993 }
1994
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001995 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001996 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001997 Op->CC.Val = CC;
1998 Op->StartLoc = S;
1999 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002000 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00002001 }
2002
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002003 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002004 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002005 Op->Cop.Val = CopVal;
2006 Op->StartLoc = S;
2007 Op->EndLoc = S;
2008 return Op;
2009 }
2010
2011 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002012 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002013 Op->Cop.Val = CopVal;
2014 Op->StartLoc = S;
2015 Op->EndLoc = S;
2016 return Op;
2017 }
2018
Jim Grosbach48399582011-10-12 17:34:41 +00002019 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2020 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2021 Op->Cop.Val = Val;
2022 Op->StartLoc = S;
2023 Op->EndLoc = E;
2024 return Op;
2025 }
2026
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002027 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002028 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002029 Op->Reg.RegNum = RegNum;
2030 Op->StartLoc = S;
2031 Op->EndLoc = S;
2032 return Op;
2033 }
2034
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002035 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002036 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002037 Op->Tok.Data = Str.data();
2038 Op->Tok.Length = Str.size();
2039 Op->StartLoc = S;
2040 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002041 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002042 }
2043
Bill Wendling2063b842010-11-18 23:43:05 +00002044 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002045 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002046 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002047 Op->StartLoc = S;
2048 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002049 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002050 }
2051
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002052 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2053 unsigned SrcReg,
2054 unsigned ShiftReg,
2055 unsigned ShiftImm,
2056 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002057 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00002058 Op->RegShiftedReg.ShiftTy = ShTy;
2059 Op->RegShiftedReg.SrcReg = SrcReg;
2060 Op->RegShiftedReg.ShiftReg = ShiftReg;
2061 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002062 Op->StartLoc = S;
2063 Op->EndLoc = E;
2064 return Op;
2065 }
2066
Owen Andersonb595ed02011-07-21 18:54:16 +00002067 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2068 unsigned SrcReg,
2069 unsigned ShiftImm,
2070 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002071 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00002072 Op->RegShiftedImm.ShiftTy = ShTy;
2073 Op->RegShiftedImm.SrcReg = SrcReg;
2074 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00002075 Op->StartLoc = S;
2076 Op->EndLoc = E;
2077 return Op;
2078 }
2079
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002080 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002081 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002082 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002083 Op->ShifterImm.isASR = isASR;
2084 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002085 Op->StartLoc = S;
2086 Op->EndLoc = E;
2087 return Op;
2088 }
2089
Jim Grosbach833b9d32011-07-27 20:15:40 +00002090 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002091 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00002092 Op->RotImm.Imm = Imm;
2093 Op->StartLoc = S;
2094 Op->EndLoc = E;
2095 return Op;
2096 }
2097
Jim Grosbach864b6092011-07-28 21:34:26 +00002098 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2099 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002100 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00002101 Op->Bitfield.LSB = LSB;
2102 Op->Bitfield.Width = Width;
2103 Op->StartLoc = S;
2104 Op->EndLoc = E;
2105 return Op;
2106 }
2107
Bill Wendling2cae3272010-11-09 22:44:22 +00002108 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00002109 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002110 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002111 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002112
Jim Grosbach75461af2011-09-13 22:56:44 +00002113 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002114 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00002115 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00002116 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002117 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002118
2119 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00002120 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002121 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00002122 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00002123 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002124 Op->StartLoc = StartLoc;
2125 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00002126 return Op;
2127 }
2128
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002129 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach2f50e922011-12-15 21:44:33 +00002130 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002131 ARMOperand *Op = new ARMOperand(k_VectorList);
2132 Op->VectorList.RegNum = RegNum;
2133 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002134 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002135 Op->StartLoc = S;
2136 Op->EndLoc = E;
2137 return Op;
2138 }
2139
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002140 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002141 bool isDoubleSpaced,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002142 SMLoc S, SMLoc E) {
2143 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2144 Op->VectorList.RegNum = RegNum;
2145 Op->VectorList.Count = Count;
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002146 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002147 Op->StartLoc = S;
2148 Op->EndLoc = E;
2149 return Op;
2150 }
2151
Jim Grosbach04945c42011-12-02 00:35:16 +00002152 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002153 unsigned Index,
2154 bool isDoubleSpaced,
2155 SMLoc S, SMLoc E) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002156 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2157 Op->VectorList.RegNum = RegNum;
2158 Op->VectorList.Count = Count;
2159 Op->VectorList.LaneIndex = Index;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002160 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach04945c42011-12-02 00:35:16 +00002161 Op->StartLoc = S;
2162 Op->EndLoc = E;
2163 return Op;
2164 }
2165
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002166 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2167 MCContext &Ctx) {
2168 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2169 Op->VectorIndex.Val = Idx;
2170 Op->StartLoc = S;
2171 Op->EndLoc = E;
2172 return Op;
2173 }
2174
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002175 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002176 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002177 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002178 Op->StartLoc = S;
2179 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002180 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002181 }
2182
Jim Grosbachd3595712011-08-03 23:50:40 +00002183 static ARMOperand *CreateMem(unsigned BaseRegNum,
2184 const MCConstantExpr *OffsetImm,
2185 unsigned OffsetRegNum,
2186 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002187 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002188 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002189 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002190 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002191 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002192 Op->Memory.BaseRegNum = BaseRegNum;
2193 Op->Memory.OffsetImm = OffsetImm;
2194 Op->Memory.OffsetRegNum = OffsetRegNum;
2195 Op->Memory.ShiftType = ShiftType;
2196 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002197 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002198 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002199 Op->StartLoc = S;
2200 Op->EndLoc = E;
2201 return Op;
2202 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002203
Jim Grosbachc320c852011-08-05 21:28:30 +00002204 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2205 ARM_AM::ShiftOpc ShiftTy,
2206 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002207 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002208 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002209 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002210 Op->PostIdxReg.isAdd = isAdd;
2211 Op->PostIdxReg.ShiftTy = ShiftTy;
2212 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002213 Op->StartLoc = S;
2214 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002215 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002216 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002217
2218 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002219 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002220 Op->MBOpt.Val = Opt;
2221 Op->StartLoc = S;
2222 Op->EndLoc = S;
2223 return Op;
2224 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002225
2226 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002227 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002228 Op->IFlags.Val = IFlags;
2229 Op->StartLoc = S;
2230 Op->EndLoc = S;
2231 return Op;
2232 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002233
2234 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002235 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002236 Op->MMask.Val = MMask;
2237 Op->StartLoc = S;
2238 Op->EndLoc = S;
2239 return Op;
2240 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002241};
2242
2243} // end anonymous namespace.
2244
Jim Grosbach602aa902011-07-13 15:34:57 +00002245void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002246 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002247 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002248 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002249 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002250 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002251 OS << "<ccout " << getReg() << ">";
2252 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002253 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002254 static const char *MaskStr[] = {
2255 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2256 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2257 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002258 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2259 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2260 break;
2261 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002262 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002263 OS << "<coprocessor number: " << getCoproc() << ">";
2264 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002265 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002266 OS << "<coprocessor register: " << getCoproc() << ">";
2267 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002268 case k_CoprocOption:
2269 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2270 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002271 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002272 OS << "<mask: " << getMSRMask() << ">";
2273 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002274 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002275 getImm()->print(OS);
2276 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002277 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002278 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2279 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002280 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002281 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002282 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002283 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002284 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002285 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002286 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2287 << PostIdxReg.RegNum;
2288 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2289 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2290 << PostIdxReg.ShiftImm;
2291 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002292 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002293 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002294 OS << "<ARM_PROC::";
2295 unsigned IFlags = getProcIFlags();
2296 for (int i=2; i >= 0; --i)
2297 if (IFlags & (1 << i))
2298 OS << ARM_PROC::IFlagsToString(1 << i);
2299 OS << ">";
2300 break;
2301 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002302 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002303 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002304 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002305 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002306 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2307 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002308 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002309 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002310 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002311 << RegShiftedReg.SrcReg << " "
2312 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2313 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002314 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002315 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002316 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002317 << RegShiftedImm.SrcReg << " "
2318 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2319 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002320 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002321 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002322 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2323 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002324 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002325 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2326 << ", width: " << Bitfield.Width << ">";
2327 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002328 case k_RegisterList:
2329 case k_DPRRegisterList:
2330 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002331 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002332
Bill Wendlingbed94652010-11-09 23:28:44 +00002333 const SmallVectorImpl<unsigned> &RegList = getRegList();
2334 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002335 I = RegList.begin(), E = RegList.end(); I != E; ) {
2336 OS << *I;
2337 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002338 }
2339
2340 OS << ">";
2341 break;
2342 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002343 case k_VectorList:
2344 OS << "<vector_list " << VectorList.Count << " * "
2345 << VectorList.RegNum << ">";
2346 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002347 case k_VectorListAllLanes:
2348 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2349 << VectorList.RegNum << ">";
2350 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002351 case k_VectorListIndexed:
2352 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2353 << VectorList.Count << " * " << VectorList.RegNum << ">";
2354 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002355 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002356 OS << "'" << getToken() << "'";
2357 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002358 case k_VectorIndex:
2359 OS << "<vectorindex " << getVectorIndex() << ">";
2360 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002361 }
2362}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002363
2364/// @name Auto-generated Match Functions
2365/// {
2366
2367static unsigned MatchRegisterName(StringRef Name);
2368
2369/// }
2370
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002371bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2372 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002373 StartLoc = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002374 RegNo = tryParseRegister();
Jim Grosbachab5830e2011-12-14 02:16:11 +00002375 EndLoc = Parser.getTok().getLoc();
Roman Divacky36b1b472011-01-27 17:14:22 +00002376
2377 return (RegNo == (unsigned)-1);
2378}
2379
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002380/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002381/// and if it is a register name the token is eaten and the register number is
2382/// returned. Otherwise return -1.
2383///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002384int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002385 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002386 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002387
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002388 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002389 unsigned RegNum = MatchRegisterName(lowerCase);
2390 if (!RegNum) {
2391 RegNum = StringSwitch<unsigned>(lowerCase)
2392 .Case("r13", ARM::SP)
2393 .Case("r14", ARM::LR)
2394 .Case("r15", ARM::PC)
2395 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002396 // Additional register name aliases for 'gas' compatibility.
2397 .Case("a1", ARM::R0)
2398 .Case("a2", ARM::R1)
2399 .Case("a3", ARM::R2)
2400 .Case("a4", ARM::R3)
2401 .Case("v1", ARM::R4)
2402 .Case("v2", ARM::R5)
2403 .Case("v3", ARM::R6)
2404 .Case("v4", ARM::R7)
2405 .Case("v5", ARM::R8)
2406 .Case("v6", ARM::R9)
2407 .Case("v7", ARM::R10)
2408 .Case("v8", ARM::R11)
2409 .Case("sb", ARM::R9)
2410 .Case("sl", ARM::R10)
2411 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002412 .Default(0);
2413 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002414 if (!RegNum) {
Jim Grosbachcd22e4a2011-12-20 23:11:00 +00002415 // Check for aliases registered via .req. Canonicalize to lower case.
2416 // That's more consistent since register names are case insensitive, and
2417 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2418 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbachab5830e2011-12-14 02:16:11 +00002419 // If no match, return failure.
2420 if (Entry == RegisterReqs.end())
2421 return -1;
2422 Parser.Lex(); // Eat identifier token.
2423 return Entry->getValue();
2424 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002425
Chris Lattner44e5981c2010-10-30 04:09:10 +00002426 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002427
Chris Lattner44e5981c2010-10-30 04:09:10 +00002428 return RegNum;
2429}
Jim Grosbach99710a82010-11-01 16:44:21 +00002430
Jim Grosbachbb24c592011-07-13 18:49:30 +00002431// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2432// If a recoverable error occurs, return 1. If an irrecoverable error
2433// occurs, return -1. An irrecoverable error is one where tokens have been
2434// consumed in the process of trying to parse the shifter (i.e., when it is
2435// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002436int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002437 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2438 SMLoc S = Parser.getTok().getLoc();
2439 const AsmToken &Tok = Parser.getTok();
2440 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2441
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002442 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002443 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002444 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002445 .Case("lsl", ARM_AM::lsl)
2446 .Case("lsr", ARM_AM::lsr)
2447 .Case("asr", ARM_AM::asr)
2448 .Case("ror", ARM_AM::ror)
2449 .Case("rrx", ARM_AM::rrx)
2450 .Default(ARM_AM::no_shift);
2451
2452 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002453 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002454
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002455 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002456
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002457 // The source register for the shift has already been added to the
2458 // operand list, so we need to pop it off and combine it into the shifted
2459 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002460 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002461 if (!PrevOp->isReg())
2462 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2463 int SrcReg = PrevOp->getReg();
2464 int64_t Imm = 0;
2465 int ShiftReg = 0;
2466 if (ShiftTy == ARM_AM::rrx) {
2467 // RRX Doesn't have an explicit shift amount. The encoder expects
2468 // the shift register to be the same as the source register. Seems odd,
2469 // but OK.
2470 ShiftReg = SrcReg;
2471 } else {
2472 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002473 if (Parser.getTok().is(AsmToken::Hash) ||
2474 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002475 Parser.Lex(); // Eat hash.
2476 SMLoc ImmLoc = Parser.getTok().getLoc();
2477 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002478 if (getParser().ParseExpression(ShiftExpr)) {
2479 Error(ImmLoc, "invalid immediate shift value");
2480 return -1;
2481 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002482 // The expression must be evaluatable as an immediate.
2483 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002484 if (!CE) {
2485 Error(ImmLoc, "invalid immediate shift value");
2486 return -1;
2487 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002488 // Range check the immediate.
2489 // lsl, ror: 0 <= imm <= 31
2490 // lsr, asr: 0 <= imm <= 32
2491 Imm = CE->getValue();
2492 if (Imm < 0 ||
2493 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2494 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002495 Error(ImmLoc, "immediate shift value out of range");
2496 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002497 }
Jim Grosbach21488b82011-12-22 17:37:00 +00002498 // shift by zero is a nop. Always send it through as lsl.
2499 // ('as' compatibility)
2500 if (Imm == 0)
2501 ShiftTy = ARM_AM::lsl;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002502 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002503 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002504 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002505 if (ShiftReg == -1) {
2506 Error (L, "expected immediate or register in shift operand");
2507 return -1;
2508 }
2509 } else {
2510 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002511 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002512 return -1;
2513 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002514 }
2515
Owen Andersonb595ed02011-07-21 18:54:16 +00002516 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2517 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002518 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002519 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002520 else
2521 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2522 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002523
Jim Grosbachbb24c592011-07-13 18:49:30 +00002524 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002525}
2526
2527
Bill Wendling2063b842010-11-18 23:43:05 +00002528/// Try to parse a register name. The token must be an Identifier when called.
2529/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2530/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002531///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002532/// TODO this is likely to change to allow different register types and or to
2533/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002534bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002535tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002536 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002537 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002538 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002539 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002540
Bill Wendling2063b842010-11-18 23:43:05 +00002541 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002542
Chris Lattner44e5981c2010-10-30 04:09:10 +00002543 const AsmToken &ExclaimTok = Parser.getTok();
2544 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002545 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2546 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002547 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002548 return false;
2549 }
2550
2551 // Also check for an index operand. This is only legal for vector registers,
2552 // but that'll get caught OK in operand matching, so we don't need to
2553 // explicitly filter everything else out here.
2554 if (Parser.getTok().is(AsmToken::LBrac)) {
2555 SMLoc SIdx = Parser.getTok().getLoc();
2556 Parser.Lex(); // Eat left bracket token.
2557
2558 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002559 if (getParser().ParseExpression(ImmVal))
Jim Grosbacha2147ce2012-01-31 23:51:09 +00002560 return true;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002561 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachc8f2b782012-01-26 15:56:45 +00002562 if (!MCE)
2563 return TokError("immediate value expected for vector index");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002564
2565 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachc8f2b782012-01-26 15:56:45 +00002566 if (Parser.getTok().isNot(AsmToken::RBrac))
2567 return Error(E, "']' expected");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002568
2569 Parser.Lex(); // Eat right bracket token.
2570
2571 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2572 SIdx, E,
2573 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002574 }
2575
Bill Wendling2063b842010-11-18 23:43:05 +00002576 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002577}
2578
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002579/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2580/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2581/// "c5", ...
2582static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002583 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2584 // but efficient.
2585 switch (Name.size()) {
David Blaikie46a9f012012-01-20 21:51:11 +00002586 default: return -1;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002587 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002588 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002589 return -1;
2590 switch (Name[1]) {
2591 default: return -1;
2592 case '0': return 0;
2593 case '1': return 1;
2594 case '2': return 2;
2595 case '3': return 3;
2596 case '4': return 4;
2597 case '5': return 5;
2598 case '6': return 6;
2599 case '7': return 7;
2600 case '8': return 8;
2601 case '9': return 9;
2602 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002603 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002604 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002605 return -1;
2606 switch (Name[2]) {
2607 default: return -1;
2608 case '0': return 10;
2609 case '1': return 11;
2610 case '2': return 12;
2611 case '3': return 13;
2612 case '4': return 14;
2613 case '5': return 15;
2614 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002615 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002616}
2617
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002618/// parseITCondCode - Try to parse a condition code for an IT instruction.
2619ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2620parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2621 SMLoc S = Parser.getTok().getLoc();
2622 const AsmToken &Tok = Parser.getTok();
2623 if (!Tok.is(AsmToken::Identifier))
2624 return MatchOperand_NoMatch;
2625 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2626 .Case("eq", ARMCC::EQ)
2627 .Case("ne", ARMCC::NE)
2628 .Case("hs", ARMCC::HS)
2629 .Case("cs", ARMCC::HS)
2630 .Case("lo", ARMCC::LO)
2631 .Case("cc", ARMCC::LO)
2632 .Case("mi", ARMCC::MI)
2633 .Case("pl", ARMCC::PL)
2634 .Case("vs", ARMCC::VS)
2635 .Case("vc", ARMCC::VC)
2636 .Case("hi", ARMCC::HI)
2637 .Case("ls", ARMCC::LS)
2638 .Case("ge", ARMCC::GE)
2639 .Case("lt", ARMCC::LT)
2640 .Case("gt", ARMCC::GT)
2641 .Case("le", ARMCC::LE)
2642 .Case("al", ARMCC::AL)
2643 .Default(~0U);
2644 if (CC == ~0U)
2645 return MatchOperand_NoMatch;
2646 Parser.Lex(); // Eat the token.
2647
2648 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2649
2650 return MatchOperand_Success;
2651}
2652
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002653/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002654/// token must be an Identifier when called, and if it is a coprocessor
2655/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002656ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002657parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002658 SMLoc S = Parser.getTok().getLoc();
2659 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002660 if (Tok.isNot(AsmToken::Identifier))
2661 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002662
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002663 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002664 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002665 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002666
2667 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002668 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002669 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002670}
2671
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002672/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002673/// token must be an Identifier when called, and if it is a coprocessor
2674/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002675ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002676parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002677 SMLoc S = Parser.getTok().getLoc();
2678 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002679 if (Tok.isNot(AsmToken::Identifier))
2680 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002681
2682 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2683 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002684 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002685
2686 Parser.Lex(); // Eat identifier token.
2687 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002688 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002689}
2690
Jim Grosbach48399582011-10-12 17:34:41 +00002691/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2692/// coproc_option : '{' imm0_255 '}'
2693ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2694parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2695 SMLoc S = Parser.getTok().getLoc();
2696
2697 // If this isn't a '{', this isn't a coprocessor immediate operand.
2698 if (Parser.getTok().isNot(AsmToken::LCurly))
2699 return MatchOperand_NoMatch;
2700 Parser.Lex(); // Eat the '{'
2701
2702 const MCExpr *Expr;
2703 SMLoc Loc = Parser.getTok().getLoc();
2704 if (getParser().ParseExpression(Expr)) {
2705 Error(Loc, "illegal expression");
2706 return MatchOperand_ParseFail;
2707 }
2708 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2709 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2710 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2711 return MatchOperand_ParseFail;
2712 }
2713 int Val = CE->getValue();
2714
2715 // Check for and consume the closing '}'
2716 if (Parser.getTok().isNot(AsmToken::RCurly))
2717 return MatchOperand_ParseFail;
2718 SMLoc E = Parser.getTok().getLoc();
2719 Parser.Lex(); // Eat the '}'
2720
2721 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2722 return MatchOperand_Success;
2723}
2724
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002725// For register list parsing, we need to map from raw GPR register numbering
2726// to the enumeration values. The enumeration values aren't sorted by
2727// register number due to our using "sp", "lr" and "pc" as canonical names.
2728static unsigned getNextRegister(unsigned Reg) {
2729 // If this is a GPR, we need to do it manually, otherwise we can rely
2730 // on the sort ordering of the enumeration since the other reg-classes
2731 // are sane.
2732 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2733 return Reg + 1;
2734 switch(Reg) {
Craig Toppere55c5562012-02-07 02:50:20 +00002735 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002736 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2737 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2738 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2739 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2740 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2741 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2742 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2743 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2744 }
2745}
2746
Jim Grosbach85a23432011-11-11 21:27:40 +00002747// Return the low-subreg of a given Q register.
2748static unsigned getDRegFromQReg(unsigned QReg) {
2749 switch (QReg) {
2750 default: llvm_unreachable("expected a Q register!");
2751 case ARM::Q0: return ARM::D0;
2752 case ARM::Q1: return ARM::D2;
2753 case ARM::Q2: return ARM::D4;
2754 case ARM::Q3: return ARM::D6;
2755 case ARM::Q4: return ARM::D8;
2756 case ARM::Q5: return ARM::D10;
2757 case ARM::Q6: return ARM::D12;
2758 case ARM::Q7: return ARM::D14;
2759 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002760 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002761 case ARM::Q10: return ARM::D20;
2762 case ARM::Q11: return ARM::D22;
2763 case ARM::Q12: return ARM::D24;
2764 case ARM::Q13: return ARM::D26;
2765 case ARM::Q14: return ARM::D28;
2766 case ARM::Q15: return ARM::D30;
2767 }
2768}
2769
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002770/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002771bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002772parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002773 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002774 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002775 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002776 Parser.Lex(); // Eat '{' token.
2777 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002778
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002779 // Check the first register in the list to see what register class
2780 // this is a list of.
2781 int Reg = tryParseRegister();
2782 if (Reg == -1)
2783 return Error(RegLoc, "register expected");
2784
Jim Grosbach85a23432011-11-11 21:27:40 +00002785 // The reglist instructions have at most 16 registers, so reserve
2786 // space for that many.
2787 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2788
2789 // Allow Q regs and just interpret them as the two D sub-registers.
2790 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2791 Reg = getDRegFromQReg(Reg);
2792 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2793 ++Reg;
2794 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002795 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002796 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2797 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2798 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2799 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2800 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2801 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2802 else
2803 return Error(RegLoc, "invalid register in register list");
2804
Jim Grosbach85a23432011-11-11 21:27:40 +00002805 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002806 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002807
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002808 // This starts immediately after the first register token in the list,
2809 // so we can see either a comma or a minus (range separator) as a legal
2810 // next token.
2811 while (Parser.getTok().is(AsmToken::Comma) ||
2812 Parser.getTok().is(AsmToken::Minus)) {
2813 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002814 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002815 SMLoc EndLoc = Parser.getTok().getLoc();
2816 int EndReg = tryParseRegister();
2817 if (EndReg == -1)
2818 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002819 // Allow Q regs and just interpret them as the two D sub-registers.
2820 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2821 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002822 // If the register is the same as the start reg, there's nothing
2823 // more to do.
2824 if (Reg == EndReg)
2825 continue;
2826 // The register must be in the same register class as the first.
2827 if (!RC->contains(EndReg))
2828 return Error(EndLoc, "invalid register in register list");
2829 // Ranges must go from low to high.
2830 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2831 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002832
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002833 // Add all the registers in the range to the register list.
2834 while (Reg != EndReg) {
2835 Reg = getNextRegister(Reg);
2836 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2837 }
2838 continue;
2839 }
2840 Parser.Lex(); // Eat the comma.
2841 RegLoc = Parser.getTok().getLoc();
2842 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002843 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002844 Reg = tryParseRegister();
2845 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002846 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002847 // Allow Q regs and just interpret them as the two D sub-registers.
2848 bool isQReg = false;
2849 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2850 Reg = getDRegFromQReg(Reg);
2851 isQReg = true;
2852 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002853 // The register must be in the same register class as the first.
2854 if (!RC->contains(Reg))
2855 return Error(RegLoc, "invalid register in register list");
2856 // List must be monotonically increasing.
Jim Grosbach98bc7972011-12-08 21:34:20 +00002857 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002858 return Error(RegLoc, "register list not in ascending order");
Jim Grosbach98bc7972011-12-08 21:34:20 +00002859 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2860 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2861 ") in register list");
2862 continue;
2863 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002864 // VFP register lists must also be contiguous.
2865 // It's OK to use the enumeration values directly here rather, as the
2866 // VFP register classes have the enum sorted properly.
2867 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2868 Reg != OldReg + 1)
2869 return Error(RegLoc, "non-contiguous register range");
2870 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002871 if (isQReg)
2872 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002873 }
2874
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002875 SMLoc E = Parser.getTok().getLoc();
2876 if (Parser.getTok().isNot(AsmToken::RCurly))
2877 return Error(E, "'}' expected");
2878 Parser.Lex(); // Eat '}' token.
2879
Jim Grosbach18bf3632011-12-13 21:48:29 +00002880 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002881 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002882
2883 // The ARM system instruction variants for LDM/STM have a '^' token here.
2884 if (Parser.getTok().is(AsmToken::Caret)) {
2885 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2886 Parser.Lex(); // Eat '^' token.
2887 }
2888
Bill Wendling2063b842010-11-18 23:43:05 +00002889 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002890}
2891
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002892// Helper function to parse the lane index for vector lists.
2893ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002894parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2895 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002896 if (Parser.getTok().is(AsmToken::LBrac)) {
2897 Parser.Lex(); // Eat the '['.
2898 if (Parser.getTok().is(AsmToken::RBrac)) {
2899 // "Dn[]" is the 'all lanes' syntax.
2900 LaneKind = AllLanes;
2901 Parser.Lex(); // Eat the ']'.
2902 return MatchOperand_Success;
2903 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002904 const MCExpr *LaneIndex;
2905 SMLoc Loc = Parser.getTok().getLoc();
2906 if (getParser().ParseExpression(LaneIndex)) {
2907 Error(Loc, "illegal expression");
2908 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002909 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002910 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2911 if (!CE) {
2912 Error(Loc, "lane index must be empty or an integer");
2913 return MatchOperand_ParseFail;
2914 }
2915 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2916 Error(Parser.getTok().getLoc(), "']' expected");
2917 return MatchOperand_ParseFail;
2918 }
2919 Parser.Lex(); // Eat the ']'.
2920 int64_t Val = CE->getValue();
2921
2922 // FIXME: Make this range check context sensitive for .8, .16, .32.
2923 if (Val < 0 || Val > 7) {
2924 Error(Parser.getTok().getLoc(), "lane index out of range");
2925 return MatchOperand_ParseFail;
2926 }
2927 Index = Val;
2928 LaneKind = IndexedLane;
2929 return MatchOperand_Success;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002930 }
2931 LaneKind = NoLanes;
2932 return MatchOperand_Success;
2933}
2934
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002935// parse a vector register list
2936ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2937parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002938 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002939 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002940 SMLoc S = Parser.getTok().getLoc();
2941 // As an extension (to match gas), support a plain D register or Q register
2942 // (without encosing curly braces) as a single or double entry list,
2943 // respectively.
2944 if (Parser.getTok().is(AsmToken::Identifier)) {
2945 int Reg = tryParseRegister();
2946 if (Reg == -1)
2947 return MatchOperand_NoMatch;
2948 SMLoc E = Parser.getTok().getLoc();
2949 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002950 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002951 if (Res != MatchOperand_Success)
2952 return Res;
2953 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002954 case NoLanes:
2955 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002956 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002957 break;
2958 case AllLanes:
2959 E = Parser.getTok().getLoc();
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002960 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2961 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002962 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002963 case IndexedLane:
2964 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002965 LaneIndex,
2966 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002967 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002968 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002969 return MatchOperand_Success;
2970 }
2971 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2972 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002973 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002974 if (Res != MatchOperand_Success)
2975 return Res;
2976 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002977 case NoLanes:
2978 E = Parser.getTok().getLoc();
Jim Grosbachc988e0c2012-03-05 19:33:30 +00002979 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbach13a292c2012-03-06 22:01:44 +00002980 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach2f50e922011-12-15 21:44:33 +00002981 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002982 break;
2983 case AllLanes:
2984 E = Parser.getTok().getLoc();
Jim Grosbach13a292c2012-03-06 22:01:44 +00002985 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
2986 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002987 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2988 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002989 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002990 case IndexedLane:
2991 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002992 LaneIndex,
2993 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002994 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002995 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002996 return MatchOperand_Success;
2997 }
2998 Error(S, "vector register expected");
2999 return MatchOperand_ParseFail;
3000 }
3001
3002 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003003 return MatchOperand_NoMatch;
3004
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003005 Parser.Lex(); // Eat '{' token.
3006 SMLoc RegLoc = Parser.getTok().getLoc();
3007
3008 int Reg = tryParseRegister();
3009 if (Reg == -1) {
3010 Error(RegLoc, "register expected");
3011 return MatchOperand_ParseFail;
3012 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003013 unsigned Count = 1;
Jim Grosbachc2f16a32011-12-15 21:54:55 +00003014 int Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00003015 unsigned FirstReg = Reg;
3016 // The list is of D registers, but we also allow Q regs and just interpret
3017 // them as the two D sub-registers.
3018 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3019 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00003020 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3021 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00003022 ++Reg;
3023 ++Count;
3024 }
Jim Grosbach04945c42011-12-02 00:35:16 +00003025 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003026 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00003027
Jim Grosbache891fe82011-11-15 23:19:15 +00003028 while (Parser.getTok().is(AsmToken::Comma) ||
3029 Parser.getTok().is(AsmToken::Minus)) {
3030 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003031 if (!Spacing)
3032 Spacing = 1; // Register range implies a single spaced list.
3033 else if (Spacing == 2) {
3034 Error(Parser.getTok().getLoc(),
3035 "sequential registers in double spaced list");
3036 return MatchOperand_ParseFail;
3037 }
Jim Grosbache891fe82011-11-15 23:19:15 +00003038 Parser.Lex(); // Eat the minus.
3039 SMLoc EndLoc = Parser.getTok().getLoc();
3040 int EndReg = tryParseRegister();
3041 if (EndReg == -1) {
3042 Error(EndLoc, "register expected");
3043 return MatchOperand_ParseFail;
3044 }
3045 // Allow Q regs and just interpret them as the two D sub-registers.
3046 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3047 EndReg = getDRegFromQReg(EndReg) + 1;
3048 // If the register is the same as the start reg, there's nothing
3049 // more to do.
3050 if (Reg == EndReg)
3051 continue;
3052 // The register must be in the same register class as the first.
3053 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3054 Error(EndLoc, "invalid register in register list");
3055 return MatchOperand_ParseFail;
3056 }
3057 // Ranges must go from low to high.
3058 if (Reg > EndReg) {
3059 Error(EndLoc, "bad range in register list");
3060 return MatchOperand_ParseFail;
3061 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003062 // Parse the lane specifier if present.
3063 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003064 unsigned NextLaneIndex;
3065 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003066 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003067 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003068 Error(EndLoc, "mismatched lane index in register list");
3069 return MatchOperand_ParseFail;
3070 }
3071 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00003072
3073 // Add all the registers in the range to the register list.
3074 Count += EndReg - Reg;
3075 Reg = EndReg;
3076 continue;
3077 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003078 Parser.Lex(); // Eat the comma.
3079 RegLoc = Parser.getTok().getLoc();
3080 int OldReg = Reg;
3081 Reg = tryParseRegister();
3082 if (Reg == -1) {
3083 Error(RegLoc, "register expected");
3084 return MatchOperand_ParseFail;
3085 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003086 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003087 // It's OK to use the enumeration values directly here rather, as the
3088 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00003089 //
3090 // The list is of D registers, but we also allow Q regs and just interpret
3091 // them as the two D sub-registers.
3092 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003093 if (!Spacing)
3094 Spacing = 1; // Register range implies a single spaced list.
3095 else if (Spacing == 2) {
3096 Error(RegLoc,
3097 "invalid register in double-spaced list (must be 'D' register')");
3098 return MatchOperand_ParseFail;
3099 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003100 Reg = getDRegFromQReg(Reg);
3101 if (Reg != OldReg + 1) {
3102 Error(RegLoc, "non-contiguous register range");
3103 return MatchOperand_ParseFail;
3104 }
3105 ++Reg;
3106 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003107 // Parse the lane specifier if present.
3108 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003109 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003110 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003111 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003112 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003113 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003114 Error(EndLoc, "mismatched lane index in register list");
3115 return MatchOperand_ParseFail;
3116 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003117 continue;
3118 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00003119 // Normal D register.
3120 // Figure out the register spacing (single or double) of the list if
3121 // we don't know it already.
3122 if (!Spacing)
3123 Spacing = 1 + (Reg == OldReg + 2);
3124
3125 // Just check that it's contiguous and keep going.
3126 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003127 Error(RegLoc, "non-contiguous register range");
3128 return MatchOperand_ParseFail;
3129 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003130 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003131 // Parse the lane specifier if present.
3132 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003133 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003134 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003135 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003136 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003137 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003138 Error(EndLoc, "mismatched lane index in register list");
3139 return MatchOperand_ParseFail;
3140 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003141 }
3142
3143 SMLoc E = Parser.getTok().getLoc();
3144 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3145 Error(E, "'}' expected");
3146 return MatchOperand_ParseFail;
3147 }
3148 Parser.Lex(); // Eat '}' token.
3149
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003150 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003151 case NoLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003152 // Two-register operands have been converted to the
Jim Grosbache5307f92012-03-05 21:43:40 +00003153 // composite register classes.
3154 if (Count == 2) {
3155 const MCRegisterClass *RC = (Spacing == 1) ?
3156 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3157 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3158 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3159 }
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003160
Jim Grosbach2f50e922011-12-15 21:44:33 +00003161 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3162 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003163 break;
3164 case AllLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003165 // Two-register operands have been converted to the
3166 // composite register classes.
Jim Grosbached428bc2012-03-06 23:10:38 +00003167 if (Count == 2) {
3168 const MCRegisterClass *RC = (Spacing == 1) ?
3169 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3170 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbach13a292c2012-03-06 22:01:44 +00003171 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3172 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003173 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003174 (Spacing == 2),
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003175 S, E));
3176 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003177 case IndexedLane:
3178 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003179 LaneIndex,
3180 (Spacing == 2),
3181 S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003182 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003183 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003184 return MatchOperand_Success;
3185}
3186
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003187/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003188ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003189parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003190 SMLoc S = Parser.getTok().getLoc();
3191 const AsmToken &Tok = Parser.getTok();
3192 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3193 StringRef OptStr = Tok.getString();
3194
3195 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3196 .Case("sy", ARM_MB::SY)
3197 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003198 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003199 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003200 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003201 .Case("ishst", ARM_MB::ISHST)
3202 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003203 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003204 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003205 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003206 .Case("osh", ARM_MB::OSH)
3207 .Case("oshst", ARM_MB::OSHST)
3208 .Default(~0U);
3209
3210 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003211 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003212
3213 Parser.Lex(); // Eat identifier token.
3214 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003215 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003216}
3217
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003218/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003219ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003220parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003221 SMLoc S = Parser.getTok().getLoc();
3222 const AsmToken &Tok = Parser.getTok();
3223 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3224 StringRef IFlagsStr = Tok.getString();
3225
Owen Anderson10c5b122011-10-05 17:16:40 +00003226 // An iflags string of "none" is interpreted to mean that none of the AIF
3227 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003228 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003229 if (IFlagsStr != "none") {
3230 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3231 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3232 .Case("a", ARM_PROC::A)
3233 .Case("i", ARM_PROC::I)
3234 .Case("f", ARM_PROC::F)
3235 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003236
Owen Anderson10c5b122011-10-05 17:16:40 +00003237 // If some specific iflag is already set, it means that some letter is
3238 // present more than once, this is not acceptable.
3239 if (Flag == ~0U || (IFlags & Flag))
3240 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003241
Owen Anderson10c5b122011-10-05 17:16:40 +00003242 IFlags |= Flag;
3243 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003244 }
3245
3246 Parser.Lex(); // Eat identifier token.
3247 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3248 return MatchOperand_Success;
3249}
3250
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003251/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003252ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003253parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003254 SMLoc S = Parser.getTok().getLoc();
3255 const AsmToken &Tok = Parser.getTok();
3256 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3257 StringRef Mask = Tok.getString();
3258
James Molloy21efa7d2011-09-28 14:21:38 +00003259 if (isMClass()) {
3260 // See ARMv6-M 10.1.1
Jim Grosbachd28888d2012-03-15 21:34:14 +00003261 std::string Name = Mask.lower();
3262 unsigned FlagsVal = StringSwitch<unsigned>(Name)
James Molloy21efa7d2011-09-28 14:21:38 +00003263 .Case("apsr", 0)
3264 .Case("iapsr", 1)
3265 .Case("eapsr", 2)
3266 .Case("xpsr", 3)
3267 .Case("ipsr", 5)
3268 .Case("epsr", 6)
3269 .Case("iepsr", 7)
3270 .Case("msp", 8)
3271 .Case("psp", 9)
3272 .Case("primask", 16)
3273 .Case("basepri", 17)
3274 .Case("basepri_max", 18)
3275 .Case("faultmask", 19)
3276 .Case("control", 20)
3277 .Default(~0U);
Jim Grosbach3794d822011-12-22 17:17:10 +00003278
James Molloy21efa7d2011-09-28 14:21:38 +00003279 if (FlagsVal == ~0U)
3280 return MatchOperand_NoMatch;
3281
3282 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3283 // basepri, basepri_max and faultmask only valid for V7m.
3284 return MatchOperand_NoMatch;
Jim Grosbach3794d822011-12-22 17:17:10 +00003285
James Molloy21efa7d2011-09-28 14:21:38 +00003286 Parser.Lex(); // Eat identifier token.
3287 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3288 return MatchOperand_Success;
3289 }
3290
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003291 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3292 size_t Start = 0, Next = Mask.find('_');
3293 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003294 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003295 if (Next != StringRef::npos)
3296 Flags = Mask.slice(Next+1, Mask.size());
3297
3298 // FlagsVal contains the complete mask:
3299 // 3-0: Mask
3300 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3301 unsigned FlagsVal = 0;
3302
3303 if (SpecReg == "apsr") {
3304 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003305 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003306 .Case("g", 0x4) // same as CPSR_s
3307 .Case("nzcvqg", 0xc) // same as CPSR_fs
3308 .Default(~0U);
3309
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003310 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003311 if (!Flags.empty())
3312 return MatchOperand_NoMatch;
3313 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003314 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003315 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003316 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003317 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3318 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003319 for (int i = 0, e = Flags.size(); i != e; ++i) {
3320 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3321 .Case("c", 1)
3322 .Case("x", 2)
3323 .Case("s", 4)
3324 .Case("f", 8)
3325 .Default(~0U);
3326
3327 // If some specific flag is already set, it means that some letter is
3328 // present more than once, this is not acceptable.
3329 if (FlagsVal == ~0U || (FlagsVal & Flag))
3330 return MatchOperand_NoMatch;
3331 FlagsVal |= Flag;
3332 }
3333 } else // No match for special register.
3334 return MatchOperand_NoMatch;
3335
Owen Anderson03a173e2011-10-21 18:43:28 +00003336 // Special register without flags is NOT equivalent to "fc" flags.
3337 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3338 // two lines would enable gas compatibility at the expense of breaking
3339 // round-tripping.
3340 //
3341 // if (!FlagsVal)
3342 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003343
3344 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3345 if (SpecReg == "spsr")
3346 FlagsVal |= 16;
3347
3348 Parser.Lex(); // Eat identifier token.
3349 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3350 return MatchOperand_Success;
3351}
3352
Jim Grosbach27c1e252011-07-21 17:23:04 +00003353ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3354parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3355 int Low, int High) {
3356 const AsmToken &Tok = Parser.getTok();
3357 if (Tok.isNot(AsmToken::Identifier)) {
3358 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3359 return MatchOperand_ParseFail;
3360 }
3361 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003362 std::string LowerOp = Op.lower();
3363 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003364 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3365 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3366 return MatchOperand_ParseFail;
3367 }
3368 Parser.Lex(); // Eat shift type token.
3369
3370 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003371 if (Parser.getTok().isNot(AsmToken::Hash) &&
3372 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003373 Error(Parser.getTok().getLoc(), "'#' expected");
3374 return MatchOperand_ParseFail;
3375 }
3376 Parser.Lex(); // Eat hash token.
3377
3378 const MCExpr *ShiftAmount;
3379 SMLoc Loc = Parser.getTok().getLoc();
3380 if (getParser().ParseExpression(ShiftAmount)) {
3381 Error(Loc, "illegal expression");
3382 return MatchOperand_ParseFail;
3383 }
3384 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3385 if (!CE) {
3386 Error(Loc, "constant expression expected");
3387 return MatchOperand_ParseFail;
3388 }
3389 int Val = CE->getValue();
3390 if (Val < Low || Val > High) {
3391 Error(Loc, "immediate value out of range");
3392 return MatchOperand_ParseFail;
3393 }
3394
3395 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3396
3397 return MatchOperand_Success;
3398}
3399
Jim Grosbach0a547702011-07-22 17:44:50 +00003400ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3401parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3402 const AsmToken &Tok = Parser.getTok();
3403 SMLoc S = Tok.getLoc();
3404 if (Tok.isNot(AsmToken::Identifier)) {
3405 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3406 return MatchOperand_ParseFail;
3407 }
3408 int Val = StringSwitch<int>(Tok.getString())
3409 .Case("be", 1)
3410 .Case("le", 0)
3411 .Default(-1);
3412 Parser.Lex(); // Eat the token.
3413
3414 if (Val == -1) {
3415 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3416 return MatchOperand_ParseFail;
3417 }
3418 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3419 getContext()),
3420 S, Parser.getTok().getLoc()));
3421 return MatchOperand_Success;
3422}
3423
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003424/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3425/// instructions. Legal values are:
3426/// lsl #n 'n' in [0,31]
3427/// asr #n 'n' in [1,32]
3428/// n == 32 encoded as n == 0.
3429ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3430parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3431 const AsmToken &Tok = Parser.getTok();
3432 SMLoc S = Tok.getLoc();
3433 if (Tok.isNot(AsmToken::Identifier)) {
3434 Error(S, "shift operator 'asr' or 'lsl' expected");
3435 return MatchOperand_ParseFail;
3436 }
3437 StringRef ShiftName = Tok.getString();
3438 bool isASR;
3439 if (ShiftName == "lsl" || ShiftName == "LSL")
3440 isASR = false;
3441 else if (ShiftName == "asr" || ShiftName == "ASR")
3442 isASR = true;
3443 else {
3444 Error(S, "shift operator 'asr' or 'lsl' expected");
3445 return MatchOperand_ParseFail;
3446 }
3447 Parser.Lex(); // Eat the operator.
3448
3449 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003450 if (Parser.getTok().isNot(AsmToken::Hash) &&
3451 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003452 Error(Parser.getTok().getLoc(), "'#' expected");
3453 return MatchOperand_ParseFail;
3454 }
3455 Parser.Lex(); // Eat hash token.
3456
3457 const MCExpr *ShiftAmount;
3458 SMLoc E = Parser.getTok().getLoc();
3459 if (getParser().ParseExpression(ShiftAmount)) {
3460 Error(E, "malformed shift expression");
3461 return MatchOperand_ParseFail;
3462 }
3463 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3464 if (!CE) {
3465 Error(E, "shift amount must be an immediate");
3466 return MatchOperand_ParseFail;
3467 }
3468
3469 int64_t Val = CE->getValue();
3470 if (isASR) {
3471 // Shift amount must be in [1,32]
3472 if (Val < 1 || Val > 32) {
3473 Error(E, "'asr' shift amount must be in range [1,32]");
3474 return MatchOperand_ParseFail;
3475 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003476 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3477 if (isThumb() && Val == 32) {
3478 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3479 return MatchOperand_ParseFail;
3480 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003481 if (Val == 32) Val = 0;
3482 } else {
3483 // Shift amount must be in [1,32]
3484 if (Val < 0 || Val > 31) {
3485 Error(E, "'lsr' shift amount must be in range [0,31]");
3486 return MatchOperand_ParseFail;
3487 }
3488 }
3489
3490 E = Parser.getTok().getLoc();
3491 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3492
3493 return MatchOperand_Success;
3494}
3495
Jim Grosbach833b9d32011-07-27 20:15:40 +00003496/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3497/// of instructions. Legal values are:
3498/// ror #n 'n' in {0, 8, 16, 24}
3499ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3500parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3501 const AsmToken &Tok = Parser.getTok();
3502 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003503 if (Tok.isNot(AsmToken::Identifier))
3504 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003505 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003506 if (ShiftName != "ror" && ShiftName != "ROR")
3507 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003508 Parser.Lex(); // Eat the operator.
3509
3510 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003511 if (Parser.getTok().isNot(AsmToken::Hash) &&
3512 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003513 Error(Parser.getTok().getLoc(), "'#' expected");
3514 return MatchOperand_ParseFail;
3515 }
3516 Parser.Lex(); // Eat hash token.
3517
3518 const MCExpr *ShiftAmount;
3519 SMLoc E = Parser.getTok().getLoc();
3520 if (getParser().ParseExpression(ShiftAmount)) {
3521 Error(E, "malformed rotate expression");
3522 return MatchOperand_ParseFail;
3523 }
3524 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3525 if (!CE) {
3526 Error(E, "rotate amount must be an immediate");
3527 return MatchOperand_ParseFail;
3528 }
3529
3530 int64_t Val = CE->getValue();
3531 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3532 // normally, zero is represented in asm by omitting the rotate operand
3533 // entirely.
3534 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3535 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3536 return MatchOperand_ParseFail;
3537 }
3538
3539 E = Parser.getTok().getLoc();
3540 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3541
3542 return MatchOperand_Success;
3543}
3544
Jim Grosbach864b6092011-07-28 21:34:26 +00003545ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3546parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3547 SMLoc S = Parser.getTok().getLoc();
3548 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003549 if (Parser.getTok().isNot(AsmToken::Hash) &&
3550 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003551 Error(Parser.getTok().getLoc(), "'#' expected");
3552 return MatchOperand_ParseFail;
3553 }
3554 Parser.Lex(); // Eat hash token.
3555
3556 const MCExpr *LSBExpr;
3557 SMLoc E = Parser.getTok().getLoc();
3558 if (getParser().ParseExpression(LSBExpr)) {
3559 Error(E, "malformed immediate expression");
3560 return MatchOperand_ParseFail;
3561 }
3562 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3563 if (!CE) {
3564 Error(E, "'lsb' operand must be an immediate");
3565 return MatchOperand_ParseFail;
3566 }
3567
3568 int64_t LSB = CE->getValue();
3569 // The LSB must be in the range [0,31]
3570 if (LSB < 0 || LSB > 31) {
3571 Error(E, "'lsb' operand must be in the range [0,31]");
3572 return MatchOperand_ParseFail;
3573 }
3574 E = Parser.getTok().getLoc();
3575
3576 // Expect another immediate operand.
3577 if (Parser.getTok().isNot(AsmToken::Comma)) {
3578 Error(Parser.getTok().getLoc(), "too few operands");
3579 return MatchOperand_ParseFail;
3580 }
3581 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003582 if (Parser.getTok().isNot(AsmToken::Hash) &&
3583 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003584 Error(Parser.getTok().getLoc(), "'#' expected");
3585 return MatchOperand_ParseFail;
3586 }
3587 Parser.Lex(); // Eat hash token.
3588
3589 const MCExpr *WidthExpr;
3590 if (getParser().ParseExpression(WidthExpr)) {
3591 Error(E, "malformed immediate expression");
3592 return MatchOperand_ParseFail;
3593 }
3594 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3595 if (!CE) {
3596 Error(E, "'width' operand must be an immediate");
3597 return MatchOperand_ParseFail;
3598 }
3599
3600 int64_t Width = CE->getValue();
3601 // The LSB must be in the range [1,32-lsb]
3602 if (Width < 1 || Width > 32 - LSB) {
3603 Error(E, "'width' operand must be in the range [1,32-lsb]");
3604 return MatchOperand_ParseFail;
3605 }
3606 E = Parser.getTok().getLoc();
3607
3608 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3609
3610 return MatchOperand_Success;
3611}
3612
Jim Grosbachd3595712011-08-03 23:50:40 +00003613ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3614parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3615 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003616 // postidx_reg := '+' register {, shift}
3617 // | '-' register {, shift}
3618 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003619
3620 // This method must return MatchOperand_NoMatch without consuming any tokens
3621 // in the case where there is no match, as other alternatives take other
3622 // parse methods.
3623 AsmToken Tok = Parser.getTok();
3624 SMLoc S = Tok.getLoc();
3625 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003626 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003627 int Reg = -1;
3628 if (Tok.is(AsmToken::Plus)) {
3629 Parser.Lex(); // Eat the '+' token.
3630 haveEaten = true;
3631 } else if (Tok.is(AsmToken::Minus)) {
3632 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003633 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003634 haveEaten = true;
3635 }
3636 if (Parser.getTok().is(AsmToken::Identifier))
3637 Reg = tryParseRegister();
3638 if (Reg == -1) {
3639 if (!haveEaten)
3640 return MatchOperand_NoMatch;
3641 Error(Parser.getTok().getLoc(), "register expected");
3642 return MatchOperand_ParseFail;
3643 }
3644 SMLoc E = Parser.getTok().getLoc();
3645
Jim Grosbachc320c852011-08-05 21:28:30 +00003646 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3647 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003648 if (Parser.getTok().is(AsmToken::Comma)) {
3649 Parser.Lex(); // Eat the ','.
3650 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3651 return MatchOperand_ParseFail;
3652 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003653
3654 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3655 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003656
3657 return MatchOperand_Success;
3658}
3659
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003660ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3661parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3662 // Check for a post-index addressing register operand. Specifically:
3663 // am3offset := '+' register
3664 // | '-' register
3665 // | register
3666 // | # imm
3667 // | # + imm
3668 // | # - imm
3669
3670 // This method must return MatchOperand_NoMatch without consuming any tokens
3671 // in the case where there is no match, as other alternatives take other
3672 // parse methods.
3673 AsmToken Tok = Parser.getTok();
3674 SMLoc S = Tok.getLoc();
3675
3676 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003677 if (Parser.getTok().is(AsmToken::Hash) ||
3678 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003679 Parser.Lex(); // Eat the '#'.
3680 // Explicitly look for a '-', as we need to encode negative zero
3681 // differently.
3682 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3683 const MCExpr *Offset;
3684 if (getParser().ParseExpression(Offset))
3685 return MatchOperand_ParseFail;
3686 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3687 if (!CE) {
3688 Error(S, "constant expression expected");
3689 return MatchOperand_ParseFail;
3690 }
3691 SMLoc E = Tok.getLoc();
3692 // Negative zero is encoded as the flag value INT32_MIN.
3693 int32_t Val = CE->getValue();
3694 if (isNegative && Val == 0)
3695 Val = INT32_MIN;
3696
3697 Operands.push_back(
3698 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3699
3700 return MatchOperand_Success;
3701 }
3702
3703
3704 bool haveEaten = false;
3705 bool isAdd = true;
3706 int Reg = -1;
3707 if (Tok.is(AsmToken::Plus)) {
3708 Parser.Lex(); // Eat the '+' token.
3709 haveEaten = true;
3710 } else if (Tok.is(AsmToken::Minus)) {
3711 Parser.Lex(); // Eat the '-' token.
3712 isAdd = false;
3713 haveEaten = true;
3714 }
3715 if (Parser.getTok().is(AsmToken::Identifier))
3716 Reg = tryParseRegister();
3717 if (Reg == -1) {
3718 if (!haveEaten)
3719 return MatchOperand_NoMatch;
3720 Error(Parser.getTok().getLoc(), "register expected");
3721 return MatchOperand_ParseFail;
3722 }
3723 SMLoc E = Parser.getTok().getLoc();
3724
3725 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3726 0, S, E));
3727
3728 return MatchOperand_Success;
3729}
3730
Jim Grosbach7db8d692011-09-08 22:07:06 +00003731/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3732/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3733/// when they refer multiple MIOperands inside a single one.
3734bool ARMAsmParser::
3735cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3736 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3737 // Rt, Rt2
3738 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3739 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3740 // Create a writeback register dummy placeholder.
3741 Inst.addOperand(MCOperand::CreateReg(0));
3742 // addr
3743 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3744 // pred
3745 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3746 return true;
3747}
3748
3749/// cvtT2StrdPre - Convert parsed operands to MCInst.
3750/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3751/// when they refer multiple MIOperands inside a single one.
3752bool ARMAsmParser::
3753cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3754 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3755 // Create a writeback register dummy placeholder.
3756 Inst.addOperand(MCOperand::CreateReg(0));
3757 // Rt, Rt2
3758 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3759 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3760 // addr
3761 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3762 // pred
3763 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3764 return true;
3765}
3766
Jim Grosbachc086f682011-09-08 00:39:19 +00003767/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3768/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3769/// when they refer multiple MIOperands inside a single one.
3770bool ARMAsmParser::
3771cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3772 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3773 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3774
3775 // Create a writeback register dummy placeholder.
3776 Inst.addOperand(MCOperand::CreateImm(0));
3777
3778 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3779 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3780 return true;
3781}
3782
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003783/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3784/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3785/// when they refer multiple MIOperands inside a single one.
3786bool ARMAsmParser::
3787cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3788 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3789 // Create a writeback register dummy placeholder.
3790 Inst.addOperand(MCOperand::CreateImm(0));
3791 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3792 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3793 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3794 return true;
3795}
3796
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003797/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003798/// 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::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003801cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003802 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3803 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3804
3805 // Create a writeback register dummy placeholder.
3806 Inst.addOperand(MCOperand::CreateImm(0));
3807
Jim Grosbachd3595712011-08-03 23:50:40 +00003808 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003809 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3810 return true;
3811}
3812
Owen Anderson16d33f32011-08-26 20:43:14 +00003813/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3814/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3815/// when they refer multiple MIOperands inside a single one.
3816bool ARMAsmParser::
3817cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3818 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3819 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3820
3821 // Create a writeback register dummy placeholder.
3822 Inst.addOperand(MCOperand::CreateImm(0));
3823
3824 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3825 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3826 return true;
3827}
3828
3829
Jim Grosbachd564bf32011-08-11 19:22:40 +00003830/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3831/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3832/// when they refer multiple MIOperands inside a single one.
3833bool ARMAsmParser::
3834cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3835 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3836 // Create a writeback register dummy placeholder.
3837 Inst.addOperand(MCOperand::CreateImm(0));
3838 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3839 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3840 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3841 return true;
3842}
3843
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003844/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003845/// 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::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003848cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003849 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3850 // Create a writeback register dummy placeholder.
3851 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003852 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3853 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3854 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003855 return true;
3856}
3857
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003858/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3859/// 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::
3862cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3863 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3864 // Create a writeback register dummy placeholder.
3865 Inst.addOperand(MCOperand::CreateImm(0));
3866 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3867 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3868 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3869 return true;
3870}
3871
Jim Grosbachd3595712011-08-03 23:50:40 +00003872/// cvtLdExtTWriteBackImm - 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::
3876cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3877 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3878 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003879 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003880 // Create a writeback register dummy placeholder.
3881 Inst.addOperand(MCOperand::CreateImm(0));
3882 // addr
3883 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3884 // offset
3885 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3886 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003887 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3888 return true;
3889}
3890
Jim Grosbachd3595712011-08-03 23:50:40 +00003891/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003892/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3893/// when they refer multiple MIOperands inside a single one.
3894bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003895cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3896 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3897 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003898 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003899 // Create a writeback register dummy placeholder.
3900 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003901 // addr
3902 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3903 // offset
3904 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3905 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003906 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3907 return true;
3908}
3909
Jim Grosbachd3595712011-08-03 23:50:40 +00003910/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003911/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3912/// when they refer multiple MIOperands inside a single one.
3913bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003914cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3915 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003916 // Create a writeback register dummy placeholder.
3917 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003918 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003919 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003920 // addr
3921 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3922 // offset
3923 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3924 // pred
3925 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3926 return true;
3927}
3928
3929/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3930/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3931/// when they refer multiple MIOperands inside a single one.
3932bool ARMAsmParser::
3933cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3934 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3935 // Create a writeback register dummy placeholder.
3936 Inst.addOperand(MCOperand::CreateImm(0));
3937 // Rt
3938 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3939 // addr
3940 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3941 // offset
3942 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3943 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003944 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3945 return true;
3946}
3947
Jim Grosbach5b96b802011-08-10 20:29:19 +00003948/// cvtLdrdPre - Convert parsed operands to MCInst.
3949/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3950/// when they refer multiple MIOperands inside a single one.
3951bool ARMAsmParser::
3952cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3953 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3954 // Rt, Rt2
3955 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3956 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3957 // Create a writeback register dummy placeholder.
3958 Inst.addOperand(MCOperand::CreateImm(0));
3959 // addr
3960 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3961 // pred
3962 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3963 return true;
3964}
3965
Jim Grosbacheb09f492011-08-11 20:28:23 +00003966/// cvtStrdPre - Convert parsed operands to MCInst.
3967/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3968/// when they refer multiple MIOperands inside a single one.
3969bool ARMAsmParser::
3970cvtStrdPre(MCInst &Inst, unsigned Opcode,
3971 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3972 // Create a writeback register dummy placeholder.
3973 Inst.addOperand(MCOperand::CreateImm(0));
3974 // Rt, Rt2
3975 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3976 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3977 // addr
3978 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3979 // pred
3980 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3981 return true;
3982}
3983
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003984/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3985/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3986/// when they refer multiple MIOperands inside a single one.
3987bool ARMAsmParser::
3988cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3989 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3990 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3991 // Create a writeback register dummy placeholder.
3992 Inst.addOperand(MCOperand::CreateImm(0));
3993 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3994 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3995 return true;
3996}
3997
Jim Grosbach8e048492011-08-19 22:07:46 +00003998/// cvtThumbMultiple- 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::
4002cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4003 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4004 // The second source operand must be the same register as the destination
4005 // operand.
4006 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00004007 (((ARMOperand*)Operands[3])->getReg() !=
4008 ((ARMOperand*)Operands[5])->getReg()) &&
4009 (((ARMOperand*)Operands[3])->getReg() !=
4010 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00004011 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00004012 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00004013 return false;
4014 }
4015 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4016 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00004017 // If we have a three-operand form, make sure to set Rn to be the operand
4018 // that isn't the same as Rd.
4019 unsigned RegOp = 4;
4020 if (Operands.size() == 6 &&
4021 ((ARMOperand*)Operands[4])->getReg() ==
4022 ((ARMOperand*)Operands[3])->getReg())
4023 RegOp = 5;
4024 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4025 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00004026 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4027
4028 return true;
4029}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00004030
Jim Grosbach3ea06572011-10-24 22:16:58 +00004031bool ARMAsmParser::
4032cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4033 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4034 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00004035 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00004036 // Create a writeback register dummy placeholder.
4037 Inst.addOperand(MCOperand::CreateImm(0));
4038 // Vn
4039 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4040 // pred
4041 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4042 return true;
4043}
4044
4045bool ARMAsmParser::
4046cvtVLDwbRegister(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 // Vm
4055 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4056 // pred
4057 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4058 return true;
4059}
4060
Jim Grosbach05df4602011-10-31 21:50:31 +00004061bool ARMAsmParser::
4062cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4063 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4064 // Create a writeback register dummy placeholder.
4065 Inst.addOperand(MCOperand::CreateImm(0));
4066 // Vn
4067 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4068 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00004069 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00004070 // pred
4071 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4072 return true;
4073}
4074
4075bool ARMAsmParser::
4076cvtVSTwbRegister(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 // Vm
4083 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4084 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00004085 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00004086 // pred
4087 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4088 return true;
4089}
4090
Bill Wendlinge18980a2010-11-06 22:36:58 +00004091/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004092/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00004093bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00004094parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004095 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00004096 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00004097 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004098 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004099 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004100
Sean Callanan936b0d32010-01-19 21:44:56 +00004101 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004102 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00004103 if (BaseRegNum == -1)
4104 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004105
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004106 // The next token must either be a comma or a closing bracket.
4107 const AsmToken &Tok = Parser.getTok();
4108 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00004109 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004110
Jim Grosbachd3595712011-08-03 23:50:40 +00004111 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004112 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004113 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004114
Jim Grosbachd3595712011-08-03 23:50:40 +00004115 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004116 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00004117
Jim Grosbach40700e02011-09-19 18:42:21 +00004118 // If there's a pre-indexing writeback marker, '!', just add it as a token
4119 // operand. It's rather odd, but syntactically valid.
4120 if (Parser.getTok().is(AsmToken::Exclaim)) {
4121 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4122 Parser.Lex(); // Eat the '!'.
4123 }
4124
Jim Grosbachd3595712011-08-03 23:50:40 +00004125 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004126 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004127
Jim Grosbachd3595712011-08-03 23:50:40 +00004128 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4129 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004130
Jim Grosbacha95ec992011-10-11 17:29:55 +00004131 // If we have a ':', it's an alignment specifier.
4132 if (Parser.getTok().is(AsmToken::Colon)) {
4133 Parser.Lex(); // Eat the ':'.
4134 E = Parser.getTok().getLoc();
4135
4136 const MCExpr *Expr;
4137 if (getParser().ParseExpression(Expr))
4138 return true;
4139
4140 // The expression has to be a constant. Memory references with relocations
4141 // don't come through here, as they use the <label> forms of the relevant
4142 // instructions.
4143 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4144 if (!CE)
4145 return Error (E, "constant expression expected");
4146
4147 unsigned Align = 0;
4148 switch (CE->getValue()) {
4149 default:
Jim Grosbachcef98cd2011-12-19 18:31:43 +00004150 return Error(E,
4151 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4152 case 16: Align = 2; break;
4153 case 32: Align = 4; break;
Jim Grosbacha95ec992011-10-11 17:29:55 +00004154 case 64: Align = 8; break;
4155 case 128: Align = 16; break;
4156 case 256: Align = 32; break;
4157 }
4158
4159 // Now we should have the closing ']'
4160 E = Parser.getTok().getLoc();
4161 if (Parser.getTok().isNot(AsmToken::RBrac))
4162 return Error(E, "']' expected");
4163 Parser.Lex(); // Eat right bracket token.
4164
4165 // Don't worry about range checking the value here. That's handled by
4166 // the is*() predicates.
4167 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4168 ARM_AM::no_shift, 0, Align,
4169 false, S, E));
4170
4171 // If there's a pre-indexing writeback marker, '!', just add it as a token
4172 // operand.
4173 if (Parser.getTok().is(AsmToken::Exclaim)) {
4174 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4175 Parser.Lex(); // Eat the '!'.
4176 }
4177
4178 return false;
4179 }
4180
4181 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00004182 // offset. Be friendly and also accept a plain integer (without a leading
4183 // hash) for gas compatibility.
4184 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004185 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00004186 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004187 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00004188 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00004189 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004190
Owen Anderson967674d2011-08-29 19:36:44 +00004191 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00004192 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004193 if (getParser().ParseExpression(Offset))
4194 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004195
4196 // The expression has to be a constant. Memory references with relocations
4197 // don't come through here, as they use the <label> forms of the relevant
4198 // instructions.
4199 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4200 if (!CE)
4201 return Error (E, "constant expression expected");
4202
Owen Anderson967674d2011-08-29 19:36:44 +00004203 // If the constant was #-0, represent it as INT32_MIN.
4204 int32_t Val = CE->getValue();
4205 if (isNegative && Val == 0)
4206 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4207
Jim Grosbachd3595712011-08-03 23:50:40 +00004208 // Now we should have the closing ']'
4209 E = Parser.getTok().getLoc();
4210 if (Parser.getTok().isNot(AsmToken::RBrac))
4211 return Error(E, "']' expected");
4212 Parser.Lex(); // Eat right bracket token.
4213
4214 // Don't worry about range checking the value here. That's handled by
4215 // the is*() predicates.
4216 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004217 ARM_AM::no_shift, 0, 0,
4218 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004219
4220 // If there's a pre-indexing writeback marker, '!', just add it as a token
4221 // operand.
4222 if (Parser.getTok().is(AsmToken::Exclaim)) {
4223 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4224 Parser.Lex(); // Eat the '!'.
4225 }
4226
4227 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004228 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004229
4230 // The register offset is optionally preceded by a '+' or '-'
4231 bool isNegative = false;
4232 if (Parser.getTok().is(AsmToken::Minus)) {
4233 isNegative = true;
4234 Parser.Lex(); // Eat the '-'.
4235 } else if (Parser.getTok().is(AsmToken::Plus)) {
4236 // Nothing to do.
4237 Parser.Lex(); // Eat the '+'.
4238 }
4239
4240 E = Parser.getTok().getLoc();
4241 int OffsetRegNum = tryParseRegister();
4242 if (OffsetRegNum == -1)
4243 return Error(E, "register expected");
4244
4245 // If there's a shift operator, handle it.
4246 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004247 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004248 if (Parser.getTok().is(AsmToken::Comma)) {
4249 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004250 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004251 return true;
4252 }
4253
4254 // Now we should have the closing ']'
4255 E = Parser.getTok().getLoc();
4256 if (Parser.getTok().isNot(AsmToken::RBrac))
4257 return Error(E, "']' expected");
4258 Parser.Lex(); // Eat right bracket token.
4259
4260 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004261 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004262 S, E));
4263
Jim Grosbachc320c852011-08-05 21:28:30 +00004264 // If there's a pre-indexing writeback marker, '!', just add it as a token
4265 // operand.
4266 if (Parser.getTok().is(AsmToken::Exclaim)) {
4267 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4268 Parser.Lex(); // Eat the '!'.
4269 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004270
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004271 return false;
4272}
4273
Jim Grosbachd3595712011-08-03 23:50:40 +00004274/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004275/// ( lsl | lsr | asr | ror ) , # shift_amount
4276/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004277/// return true if it parses a shift otherwise it returns false.
4278bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4279 unsigned &Amount) {
4280 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004281 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004282 if (Tok.isNot(AsmToken::Identifier))
4283 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004284 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004285 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4286 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004287 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004288 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004289 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004290 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004291 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004292 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004293 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004294 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004295 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004296 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004297 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004298 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004299
Jim Grosbachd3595712011-08-03 23:50:40 +00004300 // rrx stands alone.
4301 Amount = 0;
4302 if (St != ARM_AM::rrx) {
4303 Loc = Parser.getTok().getLoc();
4304 // A '#' and a shift amount.
4305 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004306 if (HashTok.isNot(AsmToken::Hash) &&
4307 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004308 return Error(HashTok.getLoc(), "'#' expected");
4309 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004310
Jim Grosbachd3595712011-08-03 23:50:40 +00004311 const MCExpr *Expr;
4312 if (getParser().ParseExpression(Expr))
4313 return true;
4314 // Range check the immediate.
4315 // lsl, ror: 0 <= imm <= 31
4316 // lsr, asr: 0 <= imm <= 32
4317 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4318 if (!CE)
4319 return Error(Loc, "shift amount must be an immediate");
4320 int64_t Imm = CE->getValue();
4321 if (Imm < 0 ||
4322 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4323 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4324 return Error(Loc, "immediate shift value out of range");
4325 Amount = Imm;
4326 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004327
4328 return false;
4329}
4330
Jim Grosbache7fbce72011-10-03 23:38:36 +00004331/// parseFPImm - A floating point immediate expression operand.
4332ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4333parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004334 // Anything that can accept a floating point constant as an operand
4335 // needs to go through here, as the regular ParseExpression is
4336 // integer only.
4337 //
4338 // This routine still creates a generic Immediate operand, containing
4339 // a bitcast of the 64-bit floating point value. The various operands
4340 // that accept floats can check whether the value is valid for them
4341 // via the standard is*() predicates.
4342
Jim Grosbache7fbce72011-10-03 23:38:36 +00004343 SMLoc S = Parser.getTok().getLoc();
4344
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004345 if (Parser.getTok().isNot(AsmToken::Hash) &&
4346 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004347 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004348
4349 // Disambiguate the VMOV forms that can accept an FP immediate.
4350 // vmov.f32 <sreg>, #imm
4351 // vmov.f64 <dreg>, #imm
4352 // vmov.f32 <dreg>, #imm @ vector f32x2
4353 // vmov.f32 <qreg>, #imm @ vector f32x4
4354 //
4355 // There are also the NEON VMOV instructions which expect an
4356 // integer constant. Make sure we don't try to parse an FPImm
4357 // for these:
4358 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4359 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4360 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4361 TyOp->getToken() != ".f64"))
4362 return MatchOperand_NoMatch;
4363
Jim Grosbache7fbce72011-10-03 23:38:36 +00004364 Parser.Lex(); // Eat the '#'.
4365
4366 // Handle negation, as that still comes through as a separate token.
4367 bool isNegative = false;
4368 if (Parser.getTok().is(AsmToken::Minus)) {
4369 isNegative = true;
4370 Parser.Lex();
4371 }
4372 const AsmToken &Tok = Parser.getTok();
Jim Grosbach235c8d22012-01-19 02:47:30 +00004373 SMLoc Loc = Tok.getLoc();
Jim Grosbache7fbce72011-10-03 23:38:36 +00004374 if (Tok.is(AsmToken::Real)) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004375 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbache7fbce72011-10-03 23:38:36 +00004376 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4377 // If we had a '-' in front, toggle the sign bit.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004378 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbache7fbce72011-10-03 23:38:36 +00004379 Parser.Lex(); // Eat the token.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004380 Operands.push_back(ARMOperand::CreateImm(
4381 MCConstantExpr::Create(IntVal, getContext()),
4382 S, Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004383 return MatchOperand_Success;
4384 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004385 // Also handle plain integers. Instructions which allow floating point
4386 // immediates also allow a raw encoded 8-bit value.
Jim Grosbache7fbce72011-10-03 23:38:36 +00004387 if (Tok.is(AsmToken::Integer)) {
4388 int64_t Val = Tok.getIntVal();
4389 Parser.Lex(); // Eat the token.
4390 if (Val > 255 || Val < 0) {
Jim Grosbach235c8d22012-01-19 02:47:30 +00004391 Error(Loc, "encoded floating point value out of range");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004392 return MatchOperand_ParseFail;
4393 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004394 double RealVal = ARM_AM::getFPImmFloat(Val);
4395 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4396 Operands.push_back(ARMOperand::CreateImm(
4397 MCConstantExpr::Create(Val, getContext()), S,
4398 Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004399 return MatchOperand_Success;
4400 }
4401
Jim Grosbach235c8d22012-01-19 02:47:30 +00004402 Error(Loc, "invalid floating point immediate");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004403 return MatchOperand_ParseFail;
4404}
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004405
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004406/// Parse a arm instruction operand. For now this parses the operand regardless
4407/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004408bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004409 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004410 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004411
4412 // Check if the current operand has a custom associated parser, if so, try to
4413 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004414 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4415 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004416 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004417 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4418 // there was a match, but an error occurred, in which case, just return that
4419 // the operand parsing failed.
4420 if (ResTy == MatchOperand_ParseFail)
4421 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004422
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004423 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004424 default:
4425 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004426 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004427 case AsmToken::Identifier: {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004428 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004429 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004430 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004431 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004432 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004433 else if (Res == -1) // irrecoverable error
4434 return true;
Jim Grosbach4eda1452011-12-20 22:26:38 +00004435 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachd28888d2012-03-15 21:34:14 +00004436 if (Mnemonic == "vmrs" &&
4437 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004438 S = Parser.getTok().getLoc();
4439 Parser.Lex();
Jim Grosbachd28888d2012-03-15 21:34:14 +00004440 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004441 return false;
4442 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004443
4444 // Fall though for the Identifier case that is not a register or a
4445 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004446 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004447 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004448 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004449 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004450 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004451 // This was not a register so parse other operands that start with an
4452 // identifier (like labels) as expressions and create them as immediates.
4453 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004454 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004455 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004456 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004457 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004458 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4459 return false;
4460 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004461 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004462 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004463 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004464 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004465 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004466 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004467 // #42 -> immediate.
4468 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004469 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004470 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004471 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004472 const MCExpr *ImmVal;
4473 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004474 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004475 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004476 if (CE) {
4477 int32_t Val = CE->getValue();
4478 if (isNegative && Val == 0)
4479 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004480 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004481 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004482 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4483 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004484 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004485 case AsmToken::Colon: {
4486 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004487 // FIXME: Check it's an expression prefix,
4488 // e.g. (FOO - :lower16:BAR) isn't legal.
4489 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004490 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004491 return true;
4492
Evan Cheng965b3c72011-01-13 07:58:56 +00004493 const MCExpr *SubExprVal;
4494 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004495 return true;
4496
Evan Cheng965b3c72011-01-13 07:58:56 +00004497 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4498 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004499 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004500 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004501 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004502 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004503 }
4504}
4505
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004506// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004507// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004508bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004509 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004510
4511 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004512 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004513 Parser.Lex(); // Eat ':'
4514
4515 if (getLexer().isNot(AsmToken::Identifier)) {
4516 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4517 return true;
4518 }
4519
4520 StringRef IDVal = Parser.getTok().getIdentifier();
4521 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004522 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004523 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004524 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004525 } else {
4526 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4527 return true;
4528 }
4529 Parser.Lex();
4530
4531 if (getLexer().isNot(AsmToken::Colon)) {
4532 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4533 return true;
4534 }
4535 Parser.Lex(); // Eat the last ':'
4536 return false;
4537}
4538
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004539/// \brief Given a mnemonic, split out possible predication code and carry
4540/// setting letters to form a canonical mnemonic and flags.
4541//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004542// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004543// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004544StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004545 unsigned &PredicationCode,
4546 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004547 unsigned &ProcessorIMod,
4548 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004549 PredicationCode = ARMCC::AL;
4550 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004551 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004552
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004553 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004554 //
4555 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004556 if ((Mnemonic == "movs" && isThumb()) ||
4557 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4558 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4559 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4560 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4561 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4562 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004563 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4564 Mnemonic == "fmuls")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004565 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004566
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004567 // First, split out any predication code. Ignore mnemonics we know aren't
4568 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004569 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004570 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004571 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004572 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004573 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4574 .Case("eq", ARMCC::EQ)
4575 .Case("ne", ARMCC::NE)
4576 .Case("hs", ARMCC::HS)
4577 .Case("cs", ARMCC::HS)
4578 .Case("lo", ARMCC::LO)
4579 .Case("cc", ARMCC::LO)
4580 .Case("mi", ARMCC::MI)
4581 .Case("pl", ARMCC::PL)
4582 .Case("vs", ARMCC::VS)
4583 .Case("vc", ARMCC::VC)
4584 .Case("hi", ARMCC::HI)
4585 .Case("ls", ARMCC::LS)
4586 .Case("ge", ARMCC::GE)
4587 .Case("lt", ARMCC::LT)
4588 .Case("gt", ARMCC::GT)
4589 .Case("le", ARMCC::LE)
4590 .Case("al", ARMCC::AL)
4591 .Default(~0U);
4592 if (CC != ~0U) {
4593 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4594 PredicationCode = CC;
4595 }
Bill Wendling193961b2010-10-29 23:50:21 +00004596 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004597
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004598 // Next, determine if we have a carry setting bit. We explicitly ignore all
4599 // the instructions we know end in 's'.
4600 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004601 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004602 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4603 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4604 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004605 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004606 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach92a939a2011-12-19 19:02:41 +00004607 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbachd74560b2012-03-15 20:48:18 +00004608 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004609 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004610 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4611 CarrySetting = true;
4612 }
4613
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004614 // The "cps" instruction can have a interrupt mode operand which is glued into
4615 // the mnemonic. Check if this is the case, split it and parse the imod op
4616 if (Mnemonic.startswith("cps")) {
4617 // Split out any imod code.
4618 unsigned IMod =
4619 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4620 .Case("ie", ARM_PROC::IE)
4621 .Case("id", ARM_PROC::ID)
4622 .Default(~0U);
4623 if (IMod != ~0U) {
4624 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4625 ProcessorIMod = IMod;
4626 }
4627 }
4628
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004629 // The "it" instruction has the condition mask on the end of the mnemonic.
4630 if (Mnemonic.startswith("it")) {
4631 ITMask = Mnemonic.slice(2, Mnemonic.size());
4632 Mnemonic = Mnemonic.slice(0, 2);
4633 }
4634
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004635 return Mnemonic;
4636}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004637
4638/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4639/// inclusion of carry set or predication code operands.
4640//
4641// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004642void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004643getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004644 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004645 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4646 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004647 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004648 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004649 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004650 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004651 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004652 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004653 Mnemonic == "mla" || Mnemonic == "smlal" ||
4654 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004655 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004656 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004657 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004658
Daniel Dunbar09264122011-01-11 19:06:29 +00004659 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4660 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4661 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4662 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004663 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4664 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004665 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004666 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4667 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4668 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004669 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4670 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004671 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004672 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004673 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004674 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004675
Jim Grosbach6c45b752011-09-16 16:39:25 +00004676 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004677 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004678 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004679 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004680 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004681}
4682
Jim Grosbach7283da92011-08-16 21:12:37 +00004683bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4684 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004685 // FIXME: This is all horribly hacky. We really need a better way to deal
4686 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004687
4688 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4689 // another does not. Specifically, the MOVW instruction does not. So we
4690 // special case it here and remove the defaulted (non-setting) cc_out
4691 // operand if that's the instruction we're trying to match.
4692 //
4693 // We do this as post-processing of the explicit operands rather than just
4694 // conditionally adding the cc_out in the first place because we need
4695 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004696 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004697 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4698 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4699 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4700 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004701
4702 // Register-register 'add' for thumb does not have a cc_out operand
4703 // when there are only two register operands.
4704 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4705 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4706 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4707 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4708 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004709 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004710 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4711 // have to check the immediate range here since Thumb2 has a variant
4712 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004713 if (((isThumb() && Mnemonic == "add") ||
4714 (isThumbTwo() && Mnemonic == "sub")) &&
4715 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004716 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4717 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4718 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004719 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4720 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4721 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004722 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004723 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4724 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004725 // selecting via the generic "add" mnemonic, so to know that we
4726 // should remove the cc_out operand, we have to explicitly check that
4727 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004728 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4729 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004730 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4731 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4732 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4733 // Nest conditions rather than one big 'if' statement for readability.
4734 //
4735 // If either register is a high reg, it's either one of the SP
4736 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004737 // check against T3. If the second register is the PC, this is an
4738 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004739 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4740 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004741 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004742 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4743 return false;
4744 // If both registers are low, we're in an IT block, and the immediate is
4745 // in range, we should use encoding T1 instead, which has a cc_out.
4746 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004747 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004748 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4749 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4750 return false;
4751
4752 // Otherwise, we use encoding T4, which does not have a cc_out
4753 // operand.
4754 return true;
4755 }
4756
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004757 // The thumb2 multiply instruction doesn't have a CCOut register, so
4758 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4759 // use the 16-bit encoding or not.
4760 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4761 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4762 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4763 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4764 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4765 // If the registers aren't low regs, the destination reg isn't the
4766 // same as one of the source regs, or the cc_out operand is zero
4767 // outside of an IT block, we have to use the 32-bit encoding, so
4768 // remove the cc_out operand.
4769 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4770 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004771 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004772 !inITBlock() ||
4773 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4774 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4775 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4776 static_cast<ARMOperand*>(Operands[4])->getReg())))
4777 return true;
4778
Jim Grosbachefa7e952011-11-15 19:55:16 +00004779 // Also check the 'mul' syntax variant that doesn't specify an explicit
4780 // destination register.
4781 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4782 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4783 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4784 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4785 // If the registers aren't low regs or the cc_out operand is zero
4786 // outside of an IT block, we have to use the 32-bit encoding, so
4787 // remove the cc_out operand.
4788 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4789 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4790 !inITBlock()))
4791 return true;
4792
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004793
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004794
Jim Grosbach4b701af2011-08-24 21:42:27 +00004795 // Register-register 'add/sub' for thumb does not have a cc_out operand
4796 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4797 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4798 // right, this will result in better diagnostics (which operand is off)
4799 // anyway.
4800 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4801 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004802 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4803 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4804 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4805 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004806
Jim Grosbach7283da92011-08-16 21:12:37 +00004807 return false;
4808}
4809
Jim Grosbach12952fe2011-11-11 23:08:10 +00004810static bool isDataTypeToken(StringRef Tok) {
4811 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4812 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4813 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4814 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4815 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4816 Tok == ".f" || Tok == ".d";
4817}
4818
4819// FIXME: This bit should probably be handled via an explicit match class
4820// in the .td files that matches the suffix instead of having it be
4821// a literal string token the way it is now.
4822static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4823 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4824}
4825
Jim Grosbach8be2f652011-12-09 23:34:09 +00004826static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004827/// Parse an arm instruction mnemonic followed by its operands.
4828bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4829 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004830 // Apply mnemonic aliases before doing anything else, as the destination
4831 // mnemnonic may include suffices and we want to handle them normally.
4832 // The generic tblgen'erated code does this later, at the start of
4833 // MatchInstructionImpl(), but that's too late for aliases that include
4834 // any sort of suffix.
4835 unsigned AvailableFeatures = getAvailableFeatures();
4836 applyMnemonicAliases(Name, AvailableFeatures);
4837
Jim Grosbachab5830e2011-12-14 02:16:11 +00004838 // First check for the ARM-specific .req directive.
4839 if (Parser.getTok().is(AsmToken::Identifier) &&
4840 Parser.getTok().getIdentifier() == ".req") {
4841 parseDirectiveReq(Name, NameLoc);
4842 // We always return 'error' for this, as we're done with this
4843 // statement and don't need to match the 'instruction."
4844 return true;
4845 }
4846
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004847 // Create the leading tokens for the mnemonic, split by '.' characters.
4848 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004849 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004850
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004851 // Split out the predication code and carry setting flag from the mnemonic.
4852 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004853 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004854 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004855 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004856 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004857 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004858
Jim Grosbach1c171b12011-08-25 17:23:55 +00004859 // In Thumb1, only the branch (B) instruction can be predicated.
4860 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4861 Parser.EatToEndOfStatement();
4862 return Error(NameLoc, "conditional execution not supported in Thumb1");
4863 }
4864
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004865 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4866
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004867 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4868 // is the mask as it will be for the IT encoding if the conditional
4869 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4870 // where the conditional bit0 is zero, the instruction post-processing
4871 // will adjust the mask accordingly.
4872 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004873 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4874 if (ITMask.size() > 3) {
4875 Parser.EatToEndOfStatement();
4876 return Error(Loc, "too many conditions on IT instruction");
4877 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004878 unsigned Mask = 8;
4879 for (unsigned i = ITMask.size(); i != 0; --i) {
4880 char pos = ITMask[i - 1];
4881 if (pos != 't' && pos != 'e') {
4882 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004883 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004884 }
4885 Mask >>= 1;
4886 if (ITMask[i - 1] == 't')
4887 Mask |= 8;
4888 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004889 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004890 }
4891
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004892 // FIXME: This is all a pretty gross hack. We should automatically handle
4893 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004894
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004895 // Next, add the CCOut and ConditionCode operands, if needed.
4896 //
4897 // For mnemonics which can ever incorporate a carry setting bit or predication
4898 // code, our matching model involves us always generating CCOut and
4899 // ConditionCode operands to match the mnemonic "as written" and then we let
4900 // the matcher deal with finding the right instruction or generating an
4901 // appropriate error.
4902 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004903 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004904
Jim Grosbach03a8a162011-07-14 22:04:21 +00004905 // If we had a carry-set on an instruction that can't do that, issue an
4906 // error.
4907 if (!CanAcceptCarrySet && CarrySetting) {
4908 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004909 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004910 "' can not set flags, but 's' suffix specified");
4911 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004912 // If we had a predication code on an instruction that can't do that, issue an
4913 // error.
4914 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4915 Parser.EatToEndOfStatement();
4916 return Error(NameLoc, "instruction '" + Mnemonic +
4917 "' is not predicable, but condition code specified");
4918 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004919
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004920 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004921 if (CanAcceptCarrySet) {
4922 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004923 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004924 Loc));
4925 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004926
4927 // Add the predication code operand, if necessary.
4928 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004929 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4930 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004931 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004932 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004933 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004934
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004935 // Add the processor imod operand, if necessary.
4936 if (ProcessorIMod) {
4937 Operands.push_back(ARMOperand::CreateImm(
4938 MCConstantExpr::Create(ProcessorIMod, getContext()),
4939 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004940 }
4941
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004942 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004943 while (Next != StringRef::npos) {
4944 Start = Next;
4945 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004946 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004947
Jim Grosbach12952fe2011-11-11 23:08:10 +00004948 // Some NEON instructions have an optional datatype suffix that is
4949 // completely ignored. Check for that.
4950 if (isDataTypeToken(ExtraToken) &&
4951 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4952 continue;
4953
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004954 if (ExtraToken != ".n") {
4955 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4956 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4957 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004958 }
4959
4960 // Read the remaining operands.
4961 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004962 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004963 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004964 Parser.EatToEndOfStatement();
4965 return true;
4966 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004967
4968 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004969 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004970
4971 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004972 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004973 Parser.EatToEndOfStatement();
4974 return true;
4975 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004976 }
4977 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004978
Chris Lattnera2a9d162010-09-11 16:18:25 +00004979 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004980 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004981 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004982 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004983 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004984
Chris Lattner91689c12010-09-08 05:10:46 +00004985 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004986
Jim Grosbach7283da92011-08-16 21:12:37 +00004987 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4988 // do and don't have a cc_out optional-def operand. With some spot-checks
4989 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004990 // parse and adjust accordingly before actually matching. We shouldn't ever
4991 // try to remove a cc_out operand that was explicitly set on the the
4992 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4993 // table driven matcher doesn't fit well with the ARM instruction set.
4994 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004995 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4996 Operands.erase(Operands.begin() + 1);
4997 delete Op;
4998 }
4999
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005000 // ARM mode 'blx' need special handling, as the register operand version
5001 // is predicable, but the label operand version is not. So, we can't rely
5002 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00005003 // a k_CondCode operand in the list. If we're trying to match the label
5004 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005005 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5006 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5007 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5008 Operands.erase(Operands.begin() + 1);
5009 delete Op;
5010 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00005011
5012 // The vector-compare-to-zero instructions have a literal token "#0" at
5013 // the end that comes to here as an immediate operand. Convert it to a
5014 // token to play nicely with the matcher.
5015 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5016 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5017 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5018 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5019 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5020 if (CE && CE->getValue() == 0) {
5021 Operands.erase(Operands.begin() + 5);
5022 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5023 delete Op;
5024 }
5025 }
Jim Grosbach46b66462011-10-03 22:30:24 +00005026 // VCMP{E} does the same thing, but with a different operand count.
5027 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5028 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5029 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5030 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5031 if (CE && CE->getValue() == 0) {
5032 Operands.erase(Operands.begin() + 4);
5033 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5034 delete Op;
5035 }
5036 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005037 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005038 // end. Convert it to a token here. Take care not to convert those
5039 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005040 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005041 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5042 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005043 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5044 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5045 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005046 if (CE && CE->getValue() == 0 &&
5047 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00005048 // The cc_out operand matches the IT block.
5049 ((inITBlock() != CarrySetting) &&
5050 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005051 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00005052 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005053 Operands.erase(Operands.begin() + 5);
5054 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5055 delete Op;
5056 }
5057 }
5058
Chris Lattnerf29c0b62010-01-14 22:21:20 +00005059 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00005060}
5061
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005062// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005063
5064// return 'true' if register list contains non-low GPR registers,
5065// 'false' otherwise. If Reg is in the register list or is HiReg, set
5066// 'containsReg' to true.
5067static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5068 unsigned HiReg, bool &containsReg) {
5069 containsReg = false;
5070 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5071 unsigned OpReg = Inst.getOperand(i).getReg();
5072 if (OpReg == Reg)
5073 containsReg = true;
5074 // Anything other than a low register isn't legal here.
5075 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5076 return true;
5077 }
5078 return false;
5079}
5080
Jim Grosbacha31f2232011-09-07 18:05:34 +00005081// Check if the specified regisgter is in the register list of the inst,
5082// starting at the indicated operand number.
5083static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5084 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5085 unsigned OpReg = Inst.getOperand(i).getReg();
5086 if (OpReg == Reg)
5087 return true;
5088 }
5089 return false;
5090}
5091
Jim Grosbached16ec42011-08-29 22:24:09 +00005092// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5093// the ARMInsts array) instead. Getting that here requires awkward
5094// API changes, though. Better way?
5095namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005096extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00005097}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005098static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005099 return ARMInsts[Opcode];
5100}
5101
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005102// FIXME: We would really like to be able to tablegen'erate this.
5103bool ARMAsmParser::
5104validateInstruction(MCInst &Inst,
5105 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005106 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00005107 SMLoc Loc = Operands[0]->getStartLoc();
5108 // Check the IT block state first.
Jim Grosbach82f76d12012-01-25 19:52:01 +00005109 // NOTE: BKPT instruction has the interesting property of being
5110 // allowed in IT blocks, but not being predicable. It just always
Owen Anderson44ae2da2011-09-13 17:59:19 +00005111 // executes.
Jim Grosbach82f76d12012-01-25 19:52:01 +00005112 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5113 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005114 unsigned bit = 1;
5115 if (ITState.FirstCond)
5116 ITState.FirstCond = false;
5117 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005118 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00005119 // The instruction must be predicable.
5120 if (!MCID.isPredicable())
5121 return Error(Loc, "instructions in IT block must be predicable");
5122 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5123 unsigned ITCond = bit ? ITState.Cond :
5124 ARMCC::getOppositeCondition(ITState.Cond);
5125 if (Cond != ITCond) {
5126 // Find the condition code Operand to get its SMLoc information.
5127 SMLoc CondLoc;
5128 for (unsigned i = 1; i < Operands.size(); ++i)
5129 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5130 CondLoc = Operands[i]->getStartLoc();
5131 return Error(CondLoc, "incorrect condition in IT block; got '" +
5132 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5133 "', but expected '" +
5134 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5135 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00005136 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005137 } else if (isThumbTwo() && MCID.isPredicable() &&
5138 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005139 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5140 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00005141 return Error(Loc, "predicated instructions must be in IT block");
5142
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005143 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00005144 case ARM::LDRD:
5145 case ARM::LDRD_PRE:
5146 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005147 case ARM::LDREXD: {
5148 // Rt2 must be Rt + 1.
5149 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5150 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5151 if (Rt2 != Rt + 1)
5152 return Error(Operands[3]->getStartLoc(),
5153 "destination operands must be sequential");
5154 return false;
5155 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00005156 case ARM::STRD: {
5157 // Rt2 must be Rt + 1.
5158 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5159 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5160 if (Rt2 != Rt + 1)
5161 return Error(Operands[3]->getStartLoc(),
5162 "source operands must be sequential");
5163 return false;
5164 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00005165 case ARM::STRD_PRE:
5166 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005167 case ARM::STREXD: {
5168 // Rt2 must be Rt + 1.
5169 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5170 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5171 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00005172 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005173 "source operands must be sequential");
5174 return false;
5175 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00005176 case ARM::SBFX:
5177 case ARM::UBFX: {
5178 // width must be in range [1, 32-lsb]
5179 unsigned lsb = Inst.getOperand(2).getImm();
5180 unsigned widthm1 = Inst.getOperand(3).getImm();
5181 if (widthm1 >= 32 - lsb)
5182 return Error(Operands[5]->getStartLoc(),
5183 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00005184 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00005185 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00005186 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00005187 // If we're parsing Thumb2, the .w variant is available and handles
5188 // most cases that are normally illegal for a Thumb1 LDM
5189 // instruction. We'll make the transformation in processInstruction()
5190 // if necessary.
5191 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00005192 // Thumb LDM instructions are writeback iff the base register is not
5193 // in the register list.
5194 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00005195 bool hasWritebackToken =
5196 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5197 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00005198 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005199 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005200 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5201 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005202 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00005203 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00005204 return Error(Operands[2]->getStartLoc(),
5205 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00005206 // If we should not have writeback, there must not be a '!'. This is
5207 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005208 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00005209 return Error(Operands[3]->getStartLoc(),
5210 "writeback operator '!' not allowed when base register "
5211 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005212
5213 break;
5214 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00005215 case ARM::t2LDMIA_UPD: {
5216 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5217 return Error(Operands[4]->getStartLoc(),
5218 "writeback operator '!' not allowed when base register "
5219 "in register list");
5220 break;
5221 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005222 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5223 // so only issue a diagnostic for thumb1. The instructions will be
5224 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005225 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005226 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005227 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5228 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005229 return Error(Operands[2]->getStartLoc(),
5230 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005231 break;
5232 }
5233 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005234 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005235 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5236 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005237 return Error(Operands[2]->getStartLoc(),
5238 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005239 break;
5240 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00005241 case ARM::tSTMIA_UPD: {
5242 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00005243 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00005244 return Error(Operands[4]->getStartLoc(),
5245 "registers must be in range r0-r7");
5246 break;
5247 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005248 }
5249
5250 return false;
5251}
5252
Jim Grosbach1a747242012-01-23 23:45:44 +00005253static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbacheb538222011-12-02 22:34:51 +00005254 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00005255 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005256 // VST1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005257 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5258 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5259 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5260 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5261 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5262 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5263 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5264 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5265 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005266
5267 // VST2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005268 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5269 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5270 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5271 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5272 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005273
Jim Grosbach1e946a42012-01-24 00:43:12 +00005274 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5275 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5276 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5277 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5278 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005279
Jim Grosbach1e946a42012-01-24 00:43:12 +00005280 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5281 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5282 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5283 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5284 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbach1a747242012-01-23 23:45:44 +00005285
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005286 // VST3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005287 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5288 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5289 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5290 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5291 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5292 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5293 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5294 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5295 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5296 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5297 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5298 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5299 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5300 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5301 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005302
Jim Grosbach1a747242012-01-23 23:45:44 +00005303 // VST3
Jim Grosbach1e946a42012-01-24 00:43:12 +00005304 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5305 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5306 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5307 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5308 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5309 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5310 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5311 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5312 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5313 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5314 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5315 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5316 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5317 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5318 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5319 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5320 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5321 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbachda70eac2012-01-24 00:58:13 +00005322
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005323 // VST4LN
5324 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5325 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5326 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5327 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5328 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5329 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5330 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5331 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5332 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5333 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5334 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5335 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5336 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5337 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5338 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5339
Jim Grosbachda70eac2012-01-24 00:58:13 +00005340 // VST4
5341 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5342 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5343 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5344 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5345 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5346 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5347 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5348 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5349 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5350 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5351 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5352 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5353 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5354 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5355 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5356 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5357 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5358 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005359 }
5360}
5361
Jim Grosbach1a747242012-01-23 23:45:44 +00005362static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005363 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00005364 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005365 // VLD1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005366 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5367 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5368 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5369 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5370 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5371 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5372 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5373 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5374 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005375
5376 // VLD2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005377 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5378 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5379 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5380 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5381 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5382 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5383 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5384 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5385 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5386 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5387 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5388 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5389 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5390 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5391 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005392
Jim Grosbachb78403c2012-01-24 23:47:04 +00005393 // VLD3DUP
5394 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5395 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5396 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5397 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5398 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5399 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5400 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5401 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5402 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5403 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5404 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5405 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5406 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5407 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5408 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5409 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5410 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5411 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5412
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005413 // VLD3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005414 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5415 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5416 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5417 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5418 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5419 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5420 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5421 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5422 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5423 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5424 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5425 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5426 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5427 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5428 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005429
5430 // VLD3
Jim Grosbach1e946a42012-01-24 00:43:12 +00005431 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5432 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5433 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5434 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5435 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5436 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5437 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5438 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5439 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5440 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5441 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5442 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5443 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5444 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5445 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5446 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5447 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5448 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbached561fc2012-01-24 00:43:17 +00005449
Jim Grosbach14952a02012-01-24 18:37:25 +00005450 // VLD4LN
5451 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5452 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5453 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5454 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5455 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5456 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5457 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5458 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5459 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5460 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5461 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5462 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5463 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5464 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5465 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5466
Jim Grosbach086cbfa2012-01-25 00:01:08 +00005467 // VLD4DUP
5468 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5469 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5470 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5471 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5472 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5473 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5474 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5475 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5476 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5477 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5478 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5479 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5480 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5481 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5482 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5483 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5484 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5485 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5486
Jim Grosbached561fc2012-01-24 00:43:17 +00005487 // VLD4
5488 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5489 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5490 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5491 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5492 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5493 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5494 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5495 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5496 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5497 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5498 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5499 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5500 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5501 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5502 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5503 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5504 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5505 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005506 }
5507}
5508
Jim Grosbachafad0532011-11-10 23:42:14 +00005509bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005510processInstruction(MCInst &Inst,
5511 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5512 switch (Inst.getOpcode()) {
Jim Grosbach94298a92012-01-18 22:46:46 +00005513 // Aliases for alternate PC+imm syntax of LDR instructions.
5514 case ARM::t2LDRpcrel:
5515 Inst.setOpcode(ARM::t2LDRpci);
5516 return true;
5517 case ARM::t2LDRBpcrel:
5518 Inst.setOpcode(ARM::t2LDRBpci);
5519 return true;
5520 case ARM::t2LDRHpcrel:
5521 Inst.setOpcode(ARM::t2LDRHpci);
5522 return true;
5523 case ARM::t2LDRSBpcrel:
5524 Inst.setOpcode(ARM::t2LDRSBpci);
5525 return true;
5526 case ARM::t2LDRSHpcrel:
5527 Inst.setOpcode(ARM::t2LDRSHpci);
5528 return true;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005529 // Handle NEON VST complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005530 case ARM::VST1LNdWB_register_Asm_8:
5531 case ARM::VST1LNdWB_register_Asm_16:
5532 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005533 MCInst TmpInst;
5534 // Shuffle the operands around so the lane index operand is in the
5535 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005536 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005537 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005538 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5539 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5540 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5541 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5542 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5543 TmpInst.addOperand(Inst.getOperand(1)); // lane
5544 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5545 TmpInst.addOperand(Inst.getOperand(6));
5546 Inst = TmpInst;
5547 return true;
5548 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005549
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005550 case ARM::VST2LNdWB_register_Asm_8:
5551 case ARM::VST2LNdWB_register_Asm_16:
5552 case ARM::VST2LNdWB_register_Asm_32:
5553 case ARM::VST2LNqWB_register_Asm_16:
5554 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005555 MCInst TmpInst;
5556 // Shuffle the operands around so the lane index operand is in the
5557 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005558 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005559 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005560 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5561 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5562 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5563 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5564 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005565 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5566 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005567 TmpInst.addOperand(Inst.getOperand(1)); // lane
5568 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5569 TmpInst.addOperand(Inst.getOperand(6));
5570 Inst = TmpInst;
5571 return true;
5572 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005573
5574 case ARM::VST3LNdWB_register_Asm_8:
5575 case ARM::VST3LNdWB_register_Asm_16:
5576 case ARM::VST3LNdWB_register_Asm_32:
5577 case ARM::VST3LNqWB_register_Asm_16:
5578 case ARM::VST3LNqWB_register_Asm_32: {
5579 MCInst TmpInst;
5580 // Shuffle the operands around so the lane index operand is in the
5581 // right place.
5582 unsigned Spacing;
5583 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5584 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5585 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5586 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5587 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5588 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5589 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5590 Spacing));
5591 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5592 Spacing * 2));
5593 TmpInst.addOperand(Inst.getOperand(1)); // lane
5594 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5595 TmpInst.addOperand(Inst.getOperand(6));
5596 Inst = TmpInst;
5597 return true;
5598 }
5599
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005600 case ARM::VST4LNdWB_register_Asm_8:
5601 case ARM::VST4LNdWB_register_Asm_16:
5602 case ARM::VST4LNdWB_register_Asm_32:
5603 case ARM::VST4LNqWB_register_Asm_16:
5604 case ARM::VST4LNqWB_register_Asm_32: {
5605 MCInst TmpInst;
5606 // Shuffle the operands around so the lane index operand is in the
5607 // right place.
5608 unsigned Spacing;
5609 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5610 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5611 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5612 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5613 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5614 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5615 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5616 Spacing));
5617 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5618 Spacing * 2));
5619 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5620 Spacing * 3));
5621 TmpInst.addOperand(Inst.getOperand(1)); // lane
5622 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5623 TmpInst.addOperand(Inst.getOperand(6));
5624 Inst = TmpInst;
5625 return true;
5626 }
5627
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005628 case ARM::VST1LNdWB_fixed_Asm_8:
5629 case ARM::VST1LNdWB_fixed_Asm_16:
5630 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005631 MCInst TmpInst;
5632 // Shuffle the operands around so the lane index operand is in the
5633 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005634 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005635 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005636 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5637 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5638 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5639 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5640 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5641 TmpInst.addOperand(Inst.getOperand(1)); // lane
5642 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5643 TmpInst.addOperand(Inst.getOperand(5));
5644 Inst = TmpInst;
5645 return true;
5646 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005647
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005648 case ARM::VST2LNdWB_fixed_Asm_8:
5649 case ARM::VST2LNdWB_fixed_Asm_16:
5650 case ARM::VST2LNdWB_fixed_Asm_32:
5651 case ARM::VST2LNqWB_fixed_Asm_16:
5652 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005653 MCInst TmpInst;
5654 // Shuffle the operands around so the lane index operand is in the
5655 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005656 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005657 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005658 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5659 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5660 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5661 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5662 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005663 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5664 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005665 TmpInst.addOperand(Inst.getOperand(1)); // lane
5666 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5667 TmpInst.addOperand(Inst.getOperand(5));
5668 Inst = TmpInst;
5669 return true;
5670 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005671
5672 case ARM::VST3LNdWB_fixed_Asm_8:
5673 case ARM::VST3LNdWB_fixed_Asm_16:
5674 case ARM::VST3LNdWB_fixed_Asm_32:
5675 case ARM::VST3LNqWB_fixed_Asm_16:
5676 case ARM::VST3LNqWB_fixed_Asm_32: {
5677 MCInst TmpInst;
5678 // Shuffle the operands around so the lane index operand is in the
5679 // right place.
5680 unsigned Spacing;
5681 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5682 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5683 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5684 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5685 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5686 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5687 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5688 Spacing));
5689 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5690 Spacing * 2));
5691 TmpInst.addOperand(Inst.getOperand(1)); // lane
5692 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5693 TmpInst.addOperand(Inst.getOperand(5));
5694 Inst = TmpInst;
5695 return true;
5696 }
5697
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005698 case ARM::VST4LNdWB_fixed_Asm_8:
5699 case ARM::VST4LNdWB_fixed_Asm_16:
5700 case ARM::VST4LNdWB_fixed_Asm_32:
5701 case ARM::VST4LNqWB_fixed_Asm_16:
5702 case ARM::VST4LNqWB_fixed_Asm_32: {
5703 MCInst TmpInst;
5704 // Shuffle the operands around so the lane index operand is in the
5705 // right place.
5706 unsigned Spacing;
5707 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5708 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5709 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5710 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5711 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5712 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5713 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5714 Spacing));
5715 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5716 Spacing * 2));
5717 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5718 Spacing * 3));
5719 TmpInst.addOperand(Inst.getOperand(1)); // lane
5720 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5721 TmpInst.addOperand(Inst.getOperand(5));
5722 Inst = TmpInst;
5723 return true;
5724 }
5725
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005726 case ARM::VST1LNdAsm_8:
5727 case ARM::VST1LNdAsm_16:
5728 case ARM::VST1LNdAsm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005729 MCInst TmpInst;
5730 // Shuffle the operands around so the lane index operand is in the
5731 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005732 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005733 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005734 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5735 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5736 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5737 TmpInst.addOperand(Inst.getOperand(1)); // lane
5738 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5739 TmpInst.addOperand(Inst.getOperand(5));
5740 Inst = TmpInst;
5741 return true;
5742 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005743
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005744 case ARM::VST2LNdAsm_8:
5745 case ARM::VST2LNdAsm_16:
5746 case ARM::VST2LNdAsm_32:
5747 case ARM::VST2LNqAsm_16:
5748 case ARM::VST2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005749 MCInst TmpInst;
5750 // Shuffle the operands around so the lane index operand is in the
5751 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005752 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005753 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005754 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5755 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5756 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005757 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5758 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005759 TmpInst.addOperand(Inst.getOperand(1)); // lane
5760 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5761 TmpInst.addOperand(Inst.getOperand(5));
5762 Inst = TmpInst;
5763 return true;
5764 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005765
5766 case ARM::VST3LNdAsm_8:
5767 case ARM::VST3LNdAsm_16:
5768 case ARM::VST3LNdAsm_32:
5769 case ARM::VST3LNqAsm_16:
5770 case ARM::VST3LNqAsm_32: {
5771 MCInst TmpInst;
5772 // Shuffle the operands around so the lane index operand is in the
5773 // right place.
5774 unsigned Spacing;
5775 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5776 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5777 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5778 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5779 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5780 Spacing));
5781 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5782 Spacing * 2));
5783 TmpInst.addOperand(Inst.getOperand(1)); // lane
5784 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5785 TmpInst.addOperand(Inst.getOperand(5));
5786 Inst = TmpInst;
5787 return true;
5788 }
5789
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005790 case ARM::VST4LNdAsm_8:
5791 case ARM::VST4LNdAsm_16:
5792 case ARM::VST4LNdAsm_32:
5793 case ARM::VST4LNqAsm_16:
5794 case ARM::VST4LNqAsm_32: {
5795 MCInst TmpInst;
5796 // Shuffle the operands around so the lane index operand is in the
5797 // right place.
5798 unsigned Spacing;
5799 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5800 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5801 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5802 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5803 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5804 Spacing));
5805 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5806 Spacing * 2));
5807 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5808 Spacing * 3));
5809 TmpInst.addOperand(Inst.getOperand(1)); // lane
5810 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5811 TmpInst.addOperand(Inst.getOperand(5));
5812 Inst = TmpInst;
5813 return true;
5814 }
5815
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005816 // Handle NEON VLD complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005817 case ARM::VLD1LNdWB_register_Asm_8:
5818 case ARM::VLD1LNdWB_register_Asm_16:
5819 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005820 MCInst TmpInst;
5821 // Shuffle the operands around so the lane index operand is in the
5822 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005823 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005824 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005825 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5826 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5827 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5828 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5829 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5830 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5831 TmpInst.addOperand(Inst.getOperand(1)); // lane
5832 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5833 TmpInst.addOperand(Inst.getOperand(6));
5834 Inst = TmpInst;
5835 return true;
5836 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005837
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005838 case ARM::VLD2LNdWB_register_Asm_8:
5839 case ARM::VLD2LNdWB_register_Asm_16:
5840 case ARM::VLD2LNdWB_register_Asm_32:
5841 case ARM::VLD2LNqWB_register_Asm_16:
5842 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005843 MCInst TmpInst;
5844 // Shuffle the operands around so the lane index operand is in the
5845 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005846 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005847 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005848 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005849 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5850 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005851 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5852 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5853 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5854 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5855 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005856 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5857 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005858 TmpInst.addOperand(Inst.getOperand(1)); // lane
5859 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5860 TmpInst.addOperand(Inst.getOperand(6));
5861 Inst = TmpInst;
5862 return true;
5863 }
5864
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005865 case ARM::VLD3LNdWB_register_Asm_8:
5866 case ARM::VLD3LNdWB_register_Asm_16:
5867 case ARM::VLD3LNdWB_register_Asm_32:
5868 case ARM::VLD3LNqWB_register_Asm_16:
5869 case ARM::VLD3LNqWB_register_Asm_32: {
5870 MCInst TmpInst;
5871 // Shuffle the operands around so the lane index operand is in the
5872 // right place.
5873 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005874 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005875 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5876 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5877 Spacing));
5878 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005879 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005880 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5881 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5882 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5883 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5884 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5885 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5886 Spacing));
5887 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005888 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005889 TmpInst.addOperand(Inst.getOperand(1)); // lane
5890 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5891 TmpInst.addOperand(Inst.getOperand(6));
5892 Inst = TmpInst;
5893 return true;
5894 }
5895
Jim Grosbach14952a02012-01-24 18:37:25 +00005896 case ARM::VLD4LNdWB_register_Asm_8:
5897 case ARM::VLD4LNdWB_register_Asm_16:
5898 case ARM::VLD4LNdWB_register_Asm_32:
5899 case ARM::VLD4LNqWB_register_Asm_16:
5900 case ARM::VLD4LNqWB_register_Asm_32: {
5901 MCInst TmpInst;
5902 // Shuffle the operands around so the lane index operand is in the
5903 // right place.
5904 unsigned Spacing;
5905 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5906 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5907 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5908 Spacing));
5909 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5910 Spacing * 2));
5911 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5912 Spacing * 3));
5913 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5914 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5915 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5916 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5917 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5918 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5919 Spacing));
5920 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5921 Spacing * 2));
5922 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5923 Spacing * 3));
5924 TmpInst.addOperand(Inst.getOperand(1)); // lane
5925 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5926 TmpInst.addOperand(Inst.getOperand(6));
5927 Inst = TmpInst;
5928 return true;
5929 }
5930
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005931 case ARM::VLD1LNdWB_fixed_Asm_8:
5932 case ARM::VLD1LNdWB_fixed_Asm_16:
5933 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005934 MCInst TmpInst;
5935 // Shuffle the operands around so the lane index operand is in the
5936 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005937 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005938 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005939 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5940 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5941 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5942 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5943 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5944 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5945 TmpInst.addOperand(Inst.getOperand(1)); // lane
5946 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5947 TmpInst.addOperand(Inst.getOperand(5));
5948 Inst = TmpInst;
5949 return true;
5950 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005951
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005952 case ARM::VLD2LNdWB_fixed_Asm_8:
5953 case ARM::VLD2LNdWB_fixed_Asm_16:
5954 case ARM::VLD2LNdWB_fixed_Asm_32:
5955 case ARM::VLD2LNqWB_fixed_Asm_16:
5956 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005957 MCInst TmpInst;
5958 // Shuffle the operands around so the lane index operand is in the
5959 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005960 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005961 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005962 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005963 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5964 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005965 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5966 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5967 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5968 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5969 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005970 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5971 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005972 TmpInst.addOperand(Inst.getOperand(1)); // lane
5973 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5974 TmpInst.addOperand(Inst.getOperand(5));
5975 Inst = TmpInst;
5976 return true;
5977 }
5978
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005979 case ARM::VLD3LNdWB_fixed_Asm_8:
5980 case ARM::VLD3LNdWB_fixed_Asm_16:
5981 case ARM::VLD3LNdWB_fixed_Asm_32:
5982 case ARM::VLD3LNqWB_fixed_Asm_16:
5983 case ARM::VLD3LNqWB_fixed_Asm_32: {
5984 MCInst TmpInst;
5985 // Shuffle the operands around so the lane index operand is in the
5986 // right place.
5987 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005988 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005989 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5990 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5991 Spacing));
5992 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005993 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005994 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5995 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5996 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5997 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5998 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5999 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6000 Spacing));
6001 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006002 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006003 TmpInst.addOperand(Inst.getOperand(1)); // lane
6004 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6005 TmpInst.addOperand(Inst.getOperand(5));
6006 Inst = TmpInst;
6007 return true;
6008 }
6009
Jim Grosbach14952a02012-01-24 18:37:25 +00006010 case ARM::VLD4LNdWB_fixed_Asm_8:
6011 case ARM::VLD4LNdWB_fixed_Asm_16:
6012 case ARM::VLD4LNdWB_fixed_Asm_32:
6013 case ARM::VLD4LNqWB_fixed_Asm_16:
6014 case ARM::VLD4LNqWB_fixed_Asm_32: {
6015 MCInst TmpInst;
6016 // Shuffle the operands around so the lane index operand is in the
6017 // right place.
6018 unsigned Spacing;
6019 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6020 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6021 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6022 Spacing));
6023 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6024 Spacing * 2));
6025 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6026 Spacing * 3));
6027 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6028 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6029 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6030 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6031 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6032 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6033 Spacing));
6034 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6035 Spacing * 2));
6036 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6037 Spacing * 3));
6038 TmpInst.addOperand(Inst.getOperand(1)); // lane
6039 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6040 TmpInst.addOperand(Inst.getOperand(5));
6041 Inst = TmpInst;
6042 return true;
6043 }
6044
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006045 case ARM::VLD1LNdAsm_8:
6046 case ARM::VLD1LNdAsm_16:
6047 case ARM::VLD1LNdAsm_32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00006048 MCInst TmpInst;
6049 // Shuffle the operands around so the lane index operand is in the
6050 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006051 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006052 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach04945c42011-12-02 00:35:16 +00006053 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6054 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6055 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6056 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6057 TmpInst.addOperand(Inst.getOperand(1)); // lane
6058 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6059 TmpInst.addOperand(Inst.getOperand(5));
6060 Inst = TmpInst;
6061 return true;
6062 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006063
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006064 case ARM::VLD2LNdAsm_8:
6065 case ARM::VLD2LNdAsm_16:
6066 case ARM::VLD2LNdAsm_32:
6067 case ARM::VLD2LNqAsm_16:
6068 case ARM::VLD2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006069 MCInst TmpInst;
6070 // Shuffle the operands around so the lane index operand is in the
6071 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006072 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006073 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006074 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006075 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6076 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006077 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6078 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6079 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006080 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6081 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006082 TmpInst.addOperand(Inst.getOperand(1)); // lane
6083 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6084 TmpInst.addOperand(Inst.getOperand(5));
6085 Inst = TmpInst;
6086 return true;
6087 }
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006088
6089 case ARM::VLD3LNdAsm_8:
6090 case ARM::VLD3LNdAsm_16:
6091 case ARM::VLD3LNdAsm_32:
6092 case ARM::VLD3LNqAsm_16:
6093 case ARM::VLD3LNqAsm_32: {
6094 MCInst TmpInst;
6095 // Shuffle the operands around so the lane index operand is in the
6096 // right place.
6097 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006098 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006099 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6100 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6101 Spacing));
6102 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006103 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006104 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6105 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6106 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6107 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6108 Spacing));
6109 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006110 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006111 TmpInst.addOperand(Inst.getOperand(1)); // lane
6112 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6113 TmpInst.addOperand(Inst.getOperand(5));
6114 Inst = TmpInst;
6115 return true;
6116 }
6117
Jim Grosbach14952a02012-01-24 18:37:25 +00006118 case ARM::VLD4LNdAsm_8:
6119 case ARM::VLD4LNdAsm_16:
6120 case ARM::VLD4LNdAsm_32:
6121 case ARM::VLD4LNqAsm_16:
6122 case ARM::VLD4LNqAsm_32: {
6123 MCInst TmpInst;
6124 // Shuffle the operands around so the lane index operand is in the
6125 // right place.
6126 unsigned Spacing;
6127 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6128 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6129 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6130 Spacing));
6131 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6132 Spacing * 2));
6133 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6134 Spacing * 3));
6135 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6136 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6137 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6138 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6139 Spacing));
6140 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6141 Spacing * 2));
6142 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6143 Spacing * 3));
6144 TmpInst.addOperand(Inst.getOperand(1)); // lane
6145 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6146 TmpInst.addOperand(Inst.getOperand(5));
6147 Inst = TmpInst;
6148 return true;
6149 }
6150
Jim Grosbachb78403c2012-01-24 23:47:04 +00006151 // VLD3DUP single 3-element structure to all lanes instructions.
6152 case ARM::VLD3DUPdAsm_8:
6153 case ARM::VLD3DUPdAsm_16:
6154 case ARM::VLD3DUPdAsm_32:
6155 case ARM::VLD3DUPqAsm_8:
6156 case ARM::VLD3DUPqAsm_16:
6157 case ARM::VLD3DUPqAsm_32: {
6158 MCInst TmpInst;
6159 unsigned Spacing;
6160 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6161 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6162 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6163 Spacing));
6164 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6165 Spacing * 2));
6166 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6167 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6168 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6169 TmpInst.addOperand(Inst.getOperand(4));
6170 Inst = TmpInst;
6171 return true;
6172 }
6173
6174 case ARM::VLD3DUPdWB_fixed_Asm_8:
6175 case ARM::VLD3DUPdWB_fixed_Asm_16:
6176 case ARM::VLD3DUPdWB_fixed_Asm_32:
6177 case ARM::VLD3DUPqWB_fixed_Asm_8:
6178 case ARM::VLD3DUPqWB_fixed_Asm_16:
6179 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6180 MCInst TmpInst;
6181 unsigned Spacing;
6182 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6183 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6184 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6185 Spacing));
6186 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6187 Spacing * 2));
6188 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6189 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6190 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6191 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6192 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6193 TmpInst.addOperand(Inst.getOperand(4));
6194 Inst = TmpInst;
6195 return true;
6196 }
6197
6198 case ARM::VLD3DUPdWB_register_Asm_8:
6199 case ARM::VLD3DUPdWB_register_Asm_16:
6200 case ARM::VLD3DUPdWB_register_Asm_32:
6201 case ARM::VLD3DUPqWB_register_Asm_8:
6202 case ARM::VLD3DUPqWB_register_Asm_16:
6203 case ARM::VLD3DUPqWB_register_Asm_32: {
6204 MCInst TmpInst;
6205 unsigned Spacing;
6206 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6207 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6208 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6209 Spacing));
6210 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6211 Spacing * 2));
6212 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6213 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6214 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6215 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6216 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6217 TmpInst.addOperand(Inst.getOperand(5));
6218 Inst = TmpInst;
6219 return true;
6220 }
6221
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006222 // VLD3 multiple 3-element structure instructions.
6223 case ARM::VLD3dAsm_8:
6224 case ARM::VLD3dAsm_16:
6225 case ARM::VLD3dAsm_32:
6226 case ARM::VLD3qAsm_8:
6227 case ARM::VLD3qAsm_16:
6228 case ARM::VLD3qAsm_32: {
6229 MCInst TmpInst;
6230 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006231 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006232 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6233 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6234 Spacing));
6235 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6236 Spacing * 2));
6237 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6238 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6239 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6240 TmpInst.addOperand(Inst.getOperand(4));
6241 Inst = TmpInst;
6242 return true;
6243 }
6244
6245 case ARM::VLD3dWB_fixed_Asm_8:
6246 case ARM::VLD3dWB_fixed_Asm_16:
6247 case ARM::VLD3dWB_fixed_Asm_32:
6248 case ARM::VLD3qWB_fixed_Asm_8:
6249 case ARM::VLD3qWB_fixed_Asm_16:
6250 case ARM::VLD3qWB_fixed_Asm_32: {
6251 MCInst TmpInst;
6252 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006253 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006254 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6255 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6256 Spacing));
6257 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6258 Spacing * 2));
6259 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6260 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6261 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6262 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6263 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6264 TmpInst.addOperand(Inst.getOperand(4));
6265 Inst = TmpInst;
6266 return true;
6267 }
6268
6269 case ARM::VLD3dWB_register_Asm_8:
6270 case ARM::VLD3dWB_register_Asm_16:
6271 case ARM::VLD3dWB_register_Asm_32:
6272 case ARM::VLD3qWB_register_Asm_8:
6273 case ARM::VLD3qWB_register_Asm_16:
6274 case ARM::VLD3qWB_register_Asm_32: {
6275 MCInst TmpInst;
6276 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006277 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006278 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6279 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6280 Spacing));
6281 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6282 Spacing * 2));
6283 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6284 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6285 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6286 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6287 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6288 TmpInst.addOperand(Inst.getOperand(5));
6289 Inst = TmpInst;
6290 return true;
6291 }
6292
Jim Grosbach086cbfa2012-01-25 00:01:08 +00006293 // VLD4DUP single 3-element structure to all lanes instructions.
6294 case ARM::VLD4DUPdAsm_8:
6295 case ARM::VLD4DUPdAsm_16:
6296 case ARM::VLD4DUPdAsm_32:
6297 case ARM::VLD4DUPqAsm_8:
6298 case ARM::VLD4DUPqAsm_16:
6299 case ARM::VLD4DUPqAsm_32: {
6300 MCInst TmpInst;
6301 unsigned Spacing;
6302 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6303 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6304 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6305 Spacing));
6306 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6307 Spacing * 2));
6308 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6309 Spacing * 3));
6310 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6311 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6312 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6313 TmpInst.addOperand(Inst.getOperand(4));
6314 Inst = TmpInst;
6315 return true;
6316 }
6317
6318 case ARM::VLD4DUPdWB_fixed_Asm_8:
6319 case ARM::VLD4DUPdWB_fixed_Asm_16:
6320 case ARM::VLD4DUPdWB_fixed_Asm_32:
6321 case ARM::VLD4DUPqWB_fixed_Asm_8:
6322 case ARM::VLD4DUPqWB_fixed_Asm_16:
6323 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6324 MCInst TmpInst;
6325 unsigned Spacing;
6326 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6327 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6328 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6329 Spacing));
6330 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6331 Spacing * 2));
6332 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6333 Spacing * 3));
6334 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6335 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6336 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6337 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6338 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6339 TmpInst.addOperand(Inst.getOperand(4));
6340 Inst = TmpInst;
6341 return true;
6342 }
6343
6344 case ARM::VLD4DUPdWB_register_Asm_8:
6345 case ARM::VLD4DUPdWB_register_Asm_16:
6346 case ARM::VLD4DUPdWB_register_Asm_32:
6347 case ARM::VLD4DUPqWB_register_Asm_8:
6348 case ARM::VLD4DUPqWB_register_Asm_16:
6349 case ARM::VLD4DUPqWB_register_Asm_32: {
6350 MCInst TmpInst;
6351 unsigned Spacing;
6352 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6353 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6354 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6355 Spacing));
6356 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6357 Spacing * 2));
6358 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6359 Spacing * 3));
6360 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6361 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6362 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6363 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6364 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6365 TmpInst.addOperand(Inst.getOperand(5));
6366 Inst = TmpInst;
6367 return true;
6368 }
6369
6370 // VLD4 multiple 4-element structure instructions.
Jim Grosbached561fc2012-01-24 00:43:17 +00006371 case ARM::VLD4dAsm_8:
6372 case ARM::VLD4dAsm_16:
6373 case ARM::VLD4dAsm_32:
6374 case ARM::VLD4qAsm_8:
6375 case ARM::VLD4qAsm_16:
6376 case ARM::VLD4qAsm_32: {
6377 MCInst TmpInst;
6378 unsigned Spacing;
6379 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6380 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6381 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6382 Spacing));
6383 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6384 Spacing * 2));
6385 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6386 Spacing * 3));
6387 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6388 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6389 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6390 TmpInst.addOperand(Inst.getOperand(4));
6391 Inst = TmpInst;
6392 return true;
6393 }
6394
6395 case ARM::VLD4dWB_fixed_Asm_8:
6396 case ARM::VLD4dWB_fixed_Asm_16:
6397 case ARM::VLD4dWB_fixed_Asm_32:
6398 case ARM::VLD4qWB_fixed_Asm_8:
6399 case ARM::VLD4qWB_fixed_Asm_16:
6400 case ARM::VLD4qWB_fixed_Asm_32: {
6401 MCInst TmpInst;
6402 unsigned Spacing;
6403 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6404 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6405 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6406 Spacing));
6407 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6408 Spacing * 2));
6409 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6410 Spacing * 3));
6411 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6412 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6413 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6414 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6415 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6416 TmpInst.addOperand(Inst.getOperand(4));
6417 Inst = TmpInst;
6418 return true;
6419 }
6420
6421 case ARM::VLD4dWB_register_Asm_8:
6422 case ARM::VLD4dWB_register_Asm_16:
6423 case ARM::VLD4dWB_register_Asm_32:
6424 case ARM::VLD4qWB_register_Asm_8:
6425 case ARM::VLD4qWB_register_Asm_16:
6426 case ARM::VLD4qWB_register_Asm_32: {
6427 MCInst TmpInst;
6428 unsigned Spacing;
6429 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6430 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6431 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6432 Spacing));
6433 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6434 Spacing * 2));
6435 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6436 Spacing * 3));
6437 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6438 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6439 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6440 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6441 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6442 TmpInst.addOperand(Inst.getOperand(5));
6443 Inst = TmpInst;
6444 return true;
6445 }
6446
Jim Grosbach1a747242012-01-23 23:45:44 +00006447 // VST3 multiple 3-element structure instructions.
6448 case ARM::VST3dAsm_8:
6449 case ARM::VST3dAsm_16:
6450 case ARM::VST3dAsm_32:
6451 case ARM::VST3qAsm_8:
6452 case ARM::VST3qAsm_16:
6453 case ARM::VST3qAsm_32: {
6454 MCInst TmpInst;
6455 unsigned Spacing;
6456 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6457 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6458 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6459 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6460 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6461 Spacing));
6462 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6463 Spacing * 2));
6464 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6465 TmpInst.addOperand(Inst.getOperand(4));
6466 Inst = TmpInst;
6467 return true;
6468 }
6469
6470 case ARM::VST3dWB_fixed_Asm_8:
6471 case ARM::VST3dWB_fixed_Asm_16:
6472 case ARM::VST3dWB_fixed_Asm_32:
6473 case ARM::VST3qWB_fixed_Asm_8:
6474 case ARM::VST3qWB_fixed_Asm_16:
6475 case ARM::VST3qWB_fixed_Asm_32: {
6476 MCInst TmpInst;
6477 unsigned Spacing;
6478 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6479 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6480 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6481 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6482 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6483 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6484 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6485 Spacing));
6486 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6487 Spacing * 2));
6488 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6489 TmpInst.addOperand(Inst.getOperand(4));
6490 Inst = TmpInst;
6491 return true;
6492 }
6493
6494 case ARM::VST3dWB_register_Asm_8:
6495 case ARM::VST3dWB_register_Asm_16:
6496 case ARM::VST3dWB_register_Asm_32:
6497 case ARM::VST3qWB_register_Asm_8:
6498 case ARM::VST3qWB_register_Asm_16:
6499 case ARM::VST3qWB_register_Asm_32: {
6500 MCInst TmpInst;
6501 unsigned Spacing;
6502 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6503 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6504 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6505 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6506 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6507 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6508 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6509 Spacing));
6510 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6511 Spacing * 2));
6512 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6513 TmpInst.addOperand(Inst.getOperand(5));
6514 Inst = TmpInst;
6515 return true;
6516 }
6517
Jim Grosbachda70eac2012-01-24 00:58:13 +00006518 // VST4 multiple 3-element structure instructions.
6519 case ARM::VST4dAsm_8:
6520 case ARM::VST4dAsm_16:
6521 case ARM::VST4dAsm_32:
6522 case ARM::VST4qAsm_8:
6523 case ARM::VST4qAsm_16:
6524 case ARM::VST4qAsm_32: {
6525 MCInst TmpInst;
6526 unsigned Spacing;
6527 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6528 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6529 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6530 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6531 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6532 Spacing));
6533 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6534 Spacing * 2));
6535 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6536 Spacing * 3));
6537 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6538 TmpInst.addOperand(Inst.getOperand(4));
6539 Inst = TmpInst;
6540 return true;
6541 }
6542
6543 case ARM::VST4dWB_fixed_Asm_8:
6544 case ARM::VST4dWB_fixed_Asm_16:
6545 case ARM::VST4dWB_fixed_Asm_32:
6546 case ARM::VST4qWB_fixed_Asm_8:
6547 case ARM::VST4qWB_fixed_Asm_16:
6548 case ARM::VST4qWB_fixed_Asm_32: {
6549 MCInst TmpInst;
6550 unsigned Spacing;
6551 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6552 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6553 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6554 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6555 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6556 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6557 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6558 Spacing));
6559 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6560 Spacing * 2));
6561 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6562 Spacing * 3));
6563 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6564 TmpInst.addOperand(Inst.getOperand(4));
6565 Inst = TmpInst;
6566 return true;
6567 }
6568
6569 case ARM::VST4dWB_register_Asm_8:
6570 case ARM::VST4dWB_register_Asm_16:
6571 case ARM::VST4dWB_register_Asm_32:
6572 case ARM::VST4qWB_register_Asm_8:
6573 case ARM::VST4qWB_register_Asm_16:
6574 case ARM::VST4qWB_register_Asm_32: {
6575 MCInst TmpInst;
6576 unsigned Spacing;
6577 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6578 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6579 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6580 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6581 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6582 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6583 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6584 Spacing));
6585 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6586 Spacing * 2));
6587 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6588 Spacing * 3));
6589 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6590 TmpInst.addOperand(Inst.getOperand(5));
6591 Inst = TmpInst;
6592 return true;
6593 }
6594
Jim Grosbach485e5622011-12-13 22:45:11 +00006595 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbachb3ef7132011-12-21 20:54:00 +00006596 case ARM::t2MOVsr:
6597 case ARM::t2MOVSsr: {
6598 // Which instruction to expand to depends on the CCOut operand and
6599 // whether we're in an IT block if the register operands are low
6600 // registers.
6601 bool isNarrow = false;
6602 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6603 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6604 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6605 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6606 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6607 isNarrow = true;
6608 MCInst TmpInst;
6609 unsigned newOpc;
6610 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6611 default: llvm_unreachable("unexpected opcode!");
6612 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6613 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6614 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6615 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6616 }
6617 TmpInst.setOpcode(newOpc);
6618 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6619 if (isNarrow)
6620 TmpInst.addOperand(MCOperand::CreateReg(
6621 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6622 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6623 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6624 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6625 TmpInst.addOperand(Inst.getOperand(5));
6626 if (!isNarrow)
6627 TmpInst.addOperand(MCOperand::CreateReg(
6628 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6629 Inst = TmpInst;
6630 return true;
6631 }
Jim Grosbach485e5622011-12-13 22:45:11 +00006632 case ARM::t2MOVsi:
6633 case ARM::t2MOVSsi: {
6634 // Which instruction to expand to depends on the CCOut operand and
6635 // whether we're in an IT block if the register operands are low
6636 // registers.
6637 bool isNarrow = false;
6638 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6639 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6640 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6641 isNarrow = true;
6642 MCInst TmpInst;
6643 unsigned newOpc;
6644 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6645 default: llvm_unreachable("unexpected opcode!");
6646 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6647 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6648 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6649 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00006650 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach485e5622011-12-13 22:45:11 +00006651 }
6652 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6653 if (Ammount == 32) Ammount = 0;
6654 TmpInst.setOpcode(newOpc);
6655 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6656 if (isNarrow)
6657 TmpInst.addOperand(MCOperand::CreateReg(
6658 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6659 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00006660 if (newOpc != ARM::t2RRX)
6661 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach485e5622011-12-13 22:45:11 +00006662 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6663 TmpInst.addOperand(Inst.getOperand(4));
6664 if (!isNarrow)
6665 TmpInst.addOperand(MCOperand::CreateReg(
6666 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6667 Inst = TmpInst;
6668 return true;
6669 }
6670 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00006671 case ARM::ASRr:
6672 case ARM::LSRr:
6673 case ARM::LSLr:
6674 case ARM::RORr: {
6675 ARM_AM::ShiftOpc ShiftTy;
6676 switch(Inst.getOpcode()) {
6677 default: llvm_unreachable("unexpected opcode!");
6678 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6679 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6680 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6681 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6682 }
Jim Grosbachabcac562011-11-16 18:31:45 +00006683 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6684 MCInst TmpInst;
6685 TmpInst.setOpcode(ARM::MOVsr);
6686 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6687 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6688 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6689 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6690 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6691 TmpInst.addOperand(Inst.getOperand(4));
6692 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6693 Inst = TmpInst;
6694 return true;
6695 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00006696 case ARM::ASRi:
6697 case ARM::LSRi:
6698 case ARM::LSLi:
6699 case ARM::RORi: {
6700 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00006701 switch(Inst.getOpcode()) {
6702 default: llvm_unreachable("unexpected opcode!");
6703 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6704 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6705 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6706 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6707 }
6708 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00006709 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00006710 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6711 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00006712 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00006713 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00006714 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6715 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00006716 if (Opc == ARM::MOVsi)
6717 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00006718 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6719 TmpInst.addOperand(Inst.getOperand(4));
6720 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6721 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006722 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00006723 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00006724 case ARM::RRXi: {
6725 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6726 MCInst TmpInst;
6727 TmpInst.setOpcode(ARM::MOVsi);
6728 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6729 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6730 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6731 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6732 TmpInst.addOperand(Inst.getOperand(3));
6733 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6734 Inst = TmpInst;
6735 return true;
6736 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00006737 case ARM::t2LDMIA_UPD: {
6738 // If this is a load of a single register, then we should use
6739 // a post-indexed LDR instruction instead, per the ARM ARM.
6740 if (Inst.getNumOperands() != 5)
6741 return false;
6742 MCInst TmpInst;
6743 TmpInst.setOpcode(ARM::t2LDR_POST);
6744 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6745 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6746 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6747 TmpInst.addOperand(MCOperand::CreateImm(4));
6748 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6749 TmpInst.addOperand(Inst.getOperand(3));
6750 Inst = TmpInst;
6751 return true;
6752 }
6753 case ARM::t2STMDB_UPD: {
6754 // If this is a store of a single register, then we should use
6755 // a pre-indexed STR instruction instead, per the ARM ARM.
6756 if (Inst.getNumOperands() != 5)
6757 return false;
6758 MCInst TmpInst;
6759 TmpInst.setOpcode(ARM::t2STR_PRE);
6760 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6761 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6762 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6763 TmpInst.addOperand(MCOperand::CreateImm(-4));
6764 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6765 TmpInst.addOperand(Inst.getOperand(3));
6766 Inst = TmpInst;
6767 return true;
6768 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006769 case ARM::LDMIA_UPD:
6770 // If this is a load of a single register via a 'pop', then we should use
6771 // a post-indexed LDR instruction instead, per the ARM ARM.
6772 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6773 Inst.getNumOperands() == 5) {
6774 MCInst TmpInst;
6775 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6776 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6777 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6778 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6779 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6780 TmpInst.addOperand(MCOperand::CreateImm(4));
6781 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6782 TmpInst.addOperand(Inst.getOperand(3));
6783 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006784 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006785 }
6786 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00006787 case ARM::STMDB_UPD:
6788 // If this is a store of a single register via a 'push', then we should use
6789 // a pre-indexed STR instruction instead, per the ARM ARM.
6790 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6791 Inst.getNumOperands() == 5) {
6792 MCInst TmpInst;
6793 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6794 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6795 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6796 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6797 TmpInst.addOperand(MCOperand::CreateImm(-4));
6798 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6799 TmpInst.addOperand(Inst.getOperand(3));
6800 Inst = TmpInst;
6801 }
6802 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00006803 case ARM::t2ADDri12:
6804 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6805 // mnemonic was used (not "addw"), encoding T3 is preferred.
6806 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6807 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6808 break;
6809 Inst.setOpcode(ARM::t2ADDri);
6810 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6811 break;
6812 case ARM::t2SUBri12:
6813 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6814 // mnemonic was used (not "subw"), encoding T3 is preferred.
6815 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6816 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6817 break;
6818 Inst.setOpcode(ARM::t2SUBri);
6819 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6820 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006821 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00006822 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6823 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6824 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6825 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00006826 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006827 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006828 return true;
6829 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006830 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006831 case ARM::tSUBi8:
6832 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6833 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6834 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6835 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00006836 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006837 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006838 return true;
6839 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006840 break;
Jim Grosbache489bab2011-12-05 22:16:39 +00006841 case ARM::t2ADDrr: {
6842 // If the destination and first source operand are the same, and
6843 // there's no setting of the flags, use encoding T2 instead of T3.
6844 // Note that this is only for ADD, not SUB. This mirrors the system
6845 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6846 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6847 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00006848 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6849 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00006850 break;
6851 MCInst TmpInst;
6852 TmpInst.setOpcode(ARM::tADDhirr);
6853 TmpInst.addOperand(Inst.getOperand(0));
6854 TmpInst.addOperand(Inst.getOperand(0));
6855 TmpInst.addOperand(Inst.getOperand(2));
6856 TmpInst.addOperand(Inst.getOperand(3));
6857 TmpInst.addOperand(Inst.getOperand(4));
6858 Inst = TmpInst;
6859 return true;
6860 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006861 case ARM::tB:
6862 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006863 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006864 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006865 return true;
6866 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006867 break;
6868 case ARM::t2B:
6869 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006870 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006871 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006872 return true;
6873 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006874 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00006875 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006876 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00006877 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00006878 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00006879 return true;
6880 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00006881 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006882 case ARM::tBcc:
6883 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00006884 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006885 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00006886 return true;
6887 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00006888 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006889 case ARM::tLDMIA: {
6890 // If the register list contains any high registers, or if the writeback
6891 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6892 // instead if we're in Thumb2. Otherwise, this should have generated
6893 // an error in validateInstruction().
6894 unsigned Rn = Inst.getOperand(0).getReg();
6895 bool hasWritebackToken =
6896 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6897 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6898 bool listContainsBase;
6899 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6900 (!listContainsBase && !hasWritebackToken) ||
6901 (listContainsBase && hasWritebackToken)) {
6902 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6903 assert (isThumbTwo());
6904 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6905 // If we're switching to the updating version, we need to insert
6906 // the writeback tied operand.
6907 if (hasWritebackToken)
6908 Inst.insert(Inst.begin(),
6909 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00006910 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006911 }
6912 break;
6913 }
Jim Grosbach099c9762011-09-16 20:50:13 +00006914 case ARM::tSTMIA_UPD: {
6915 // If the register list contains any high registers, we need to use
6916 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6917 // should have generated an error in validateInstruction().
6918 unsigned Rn = Inst.getOperand(0).getReg();
6919 bool listContainsBase;
6920 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6921 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6922 assert (isThumbTwo());
6923 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00006924 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00006925 }
6926 break;
6927 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006928 case ARM::tPOP: {
6929 bool listContainsBase;
6930 // If the register list contains any high registers, we need to use
6931 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6932 // should have generated an error in validateInstruction().
6933 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006934 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006935 assert (isThumbTwo());
6936 Inst.setOpcode(ARM::t2LDMIA_UPD);
6937 // Add the base register and writeback operands.
6938 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6939 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006940 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006941 }
6942 case ARM::tPUSH: {
6943 bool listContainsBase;
6944 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006945 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006946 assert (isThumbTwo());
6947 Inst.setOpcode(ARM::t2STMDB_UPD);
6948 // Add the base register and writeback operands.
6949 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6950 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006951 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006952 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006953 case ARM::t2MOVi: {
6954 // If we can use the 16-bit encoding and the user didn't explicitly
6955 // request the 32-bit variant, transform it here.
6956 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6957 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00006958 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6959 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6960 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006961 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6962 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6963 // The operands aren't in the same order for tMOVi8...
6964 MCInst TmpInst;
6965 TmpInst.setOpcode(ARM::tMOVi8);
6966 TmpInst.addOperand(Inst.getOperand(0));
6967 TmpInst.addOperand(Inst.getOperand(4));
6968 TmpInst.addOperand(Inst.getOperand(1));
6969 TmpInst.addOperand(Inst.getOperand(2));
6970 TmpInst.addOperand(Inst.getOperand(3));
6971 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006972 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006973 }
6974 break;
6975 }
6976 case ARM::t2MOVr: {
6977 // If we can use the 16-bit encoding and the user didn't explicitly
6978 // request the 32-bit variant, transform it here.
6979 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6980 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6981 Inst.getOperand(2).getImm() == ARMCC::AL &&
6982 Inst.getOperand(4).getReg() == ARM::CPSR &&
6983 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6984 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6985 // The operands aren't the same for tMOV[S]r... (no cc_out)
6986 MCInst TmpInst;
6987 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6988 TmpInst.addOperand(Inst.getOperand(0));
6989 TmpInst.addOperand(Inst.getOperand(1));
6990 TmpInst.addOperand(Inst.getOperand(2));
6991 TmpInst.addOperand(Inst.getOperand(3));
6992 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006993 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006994 }
6995 break;
6996 }
Jim Grosbach82213192011-09-19 20:29:33 +00006997 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00006998 case ARM::t2SXTB:
6999 case ARM::t2UXTH:
7000 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00007001 // If we can use the 16-bit encoding and the user didn't explicitly
7002 // request the 32-bit variant, transform it here.
7003 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7004 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7005 Inst.getOperand(2).getImm() == 0 &&
7006 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7007 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00007008 unsigned NewOpc;
7009 switch (Inst.getOpcode()) {
7010 default: llvm_unreachable("Illegal opcode!");
7011 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7012 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7013 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7014 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7015 }
Jim Grosbach82213192011-09-19 20:29:33 +00007016 // The operands aren't the same for thumb1 (no rotate operand).
7017 MCInst TmpInst;
7018 TmpInst.setOpcode(NewOpc);
7019 TmpInst.addOperand(Inst.getOperand(0));
7020 TmpInst.addOperand(Inst.getOperand(1));
7021 TmpInst.addOperand(Inst.getOperand(3));
7022 TmpInst.addOperand(Inst.getOperand(4));
7023 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007024 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00007025 }
7026 break;
7027 }
Jim Grosbache2ca9e52011-12-20 00:59:38 +00007028 case ARM::MOVsi: {
7029 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7030 if (SOpc == ARM_AM::rrx) return false;
7031 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7032 // Shifting by zero is accepted as a vanilla 'MOVr'
7033 MCInst TmpInst;
7034 TmpInst.setOpcode(ARM::MOVr);
7035 TmpInst.addOperand(Inst.getOperand(0));
7036 TmpInst.addOperand(Inst.getOperand(1));
7037 TmpInst.addOperand(Inst.getOperand(3));
7038 TmpInst.addOperand(Inst.getOperand(4));
7039 TmpInst.addOperand(Inst.getOperand(5));
7040 Inst = TmpInst;
7041 return true;
7042 }
7043 return false;
7044 }
Jim Grosbach12ccf452011-12-22 18:04:04 +00007045 case ARM::ANDrsi:
7046 case ARM::ORRrsi:
7047 case ARM::EORrsi:
7048 case ARM::BICrsi:
7049 case ARM::SUBrsi:
7050 case ARM::ADDrsi: {
7051 unsigned newOpc;
7052 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7053 if (SOpc == ARM_AM::rrx) return false;
7054 switch (Inst.getOpcode()) {
Craig Toppere55c5562012-02-07 02:50:20 +00007055 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach12ccf452011-12-22 18:04:04 +00007056 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7057 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7058 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7059 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7060 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7061 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7062 }
7063 // If the shift is by zero, use the non-shifted instruction definition.
7064 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7065 MCInst TmpInst;
7066 TmpInst.setOpcode(newOpc);
7067 TmpInst.addOperand(Inst.getOperand(0));
7068 TmpInst.addOperand(Inst.getOperand(1));
7069 TmpInst.addOperand(Inst.getOperand(2));
7070 TmpInst.addOperand(Inst.getOperand(4));
7071 TmpInst.addOperand(Inst.getOperand(5));
7072 TmpInst.addOperand(Inst.getOperand(6));
7073 Inst = TmpInst;
7074 return true;
7075 }
7076 return false;
7077 }
Jim Grosbach82f76d12012-01-25 19:52:01 +00007078 case ARM::ITasm:
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007079 case ARM::t2IT: {
7080 // The mask bits for all but the first condition are represented as
7081 // the low bit of the condition code value implies 't'. We currently
7082 // always have 1 implies 't', so XOR toggle the bits if the low bit
7083 // of the condition code is zero. The encoding also expects the low
7084 // bit of the condition to be encoded as bit 4 of the mask operand,
7085 // so mask that in if needed
7086 MCOperand &MO = Inst.getOperand(1);
7087 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00007088 unsigned OrigMask = Mask;
7089 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007090 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007091 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7092 for (unsigned i = 3; i != TZ; --i)
7093 Mask ^= 1 << i;
7094 } else
7095 Mask |= 0x10;
7096 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00007097
7098 // Set up the IT block state according to the IT instruction we just
7099 // matched.
7100 assert(!inITBlock() && "nested IT blocks?!");
7101 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7102 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7103 ITState.CurPosition = 0;
7104 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007105 break;
7106 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007107 }
Jim Grosbachafad0532011-11-10 23:42:14 +00007108 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007109}
7110
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007111unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7112 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7113 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007114 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00007115 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007116 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7117 assert(MCID.hasOptionalDef() &&
7118 "optionally flag setting instruction missing optional def operand");
7119 assert(MCID.NumOperands == Inst.getNumOperands() &&
7120 "operand count mismatch!");
7121 // Find the optional-def operand (cc_out).
7122 unsigned OpNo;
7123 for (OpNo = 0;
7124 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7125 ++OpNo)
7126 ;
7127 // If we're parsing Thumb1, reject it completely.
7128 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7129 return Match_MnemonicFail;
7130 // If we're parsing Thumb2, which form is legal depends on whether we're
7131 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00007132 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7133 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007134 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00007135 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7136 inITBlock())
7137 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007138 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007139 // Some high-register supporting Thumb1 encodings only allow both registers
7140 // to be from r0-r7 when in Thumb2.
7141 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7142 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7143 isARMLowRegister(Inst.getOperand(2).getReg()))
7144 return Match_RequiresThumb2;
7145 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00007146 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007147 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7148 isARMLowRegister(Inst.getOperand(1).getReg()))
7149 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007150 return Match_Success;
7151}
7152
Chris Lattner9487de62010-10-28 21:28:01 +00007153bool ARMAsmParser::
7154MatchAndEmitInstruction(SMLoc IDLoc,
7155 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7156 MCStreamer &Out) {
7157 MCInst Inst;
7158 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00007159 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00007160 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00007161 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00007162 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007163 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007164 // Context sensitive operand constraints aren't handled by the matcher,
7165 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007166 if (validateInstruction(Inst, Operands)) {
7167 // Still progress the IT block, otherwise one wrong condition causes
7168 // nasty cascading errors.
7169 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007170 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007171 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007172
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007173 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00007174 // encoding is selected. Loop on it while changes happen so the
7175 // individual transformations can chain off each other. E.g.,
7176 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7177 while (processInstruction(Inst, Operands))
7178 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007179
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007180 // Only move forward at the very end so that everything in validate
7181 // and process gets a consistent answer about whether we're in an IT
7182 // block.
7183 forwardITPosition();
7184
Jim Grosbach82f76d12012-01-25 19:52:01 +00007185 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7186 // doesn't actually encode.
7187 if (Inst.getOpcode() == ARM::ITasm)
7188 return false;
7189
Jim Grosbach5e5eabb2012-01-26 23:20:15 +00007190 Inst.setLoc(IDLoc);
Chris Lattner9487de62010-10-28 21:28:01 +00007191 Out.EmitInstruction(Inst);
7192 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007193 case Match_MissingFeature:
7194 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7195 return true;
7196 case Match_InvalidOperand: {
7197 SMLoc ErrorLoc = IDLoc;
7198 if (ErrorInfo != ~0U) {
7199 if (ErrorInfo >= Operands.size())
7200 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00007201
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007202 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7203 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7204 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00007205
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007206 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00007207 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007208 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007209 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00007210 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00007211 // The converter function will have already emited a diagnostic.
7212 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00007213 case Match_RequiresNotITBlock:
7214 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007215 case Match_RequiresITBlock:
7216 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007217 case Match_RequiresV6:
7218 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7219 case Match_RequiresThumb2:
7220 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007221 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00007222
Eric Christopher91d7b902010-10-29 09:26:59 +00007223 llvm_unreachable("Implement any new match types added!");
Chris Lattner9487de62010-10-28 21:28:01 +00007224}
7225
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007226/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00007227bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7228 StringRef IDVal = DirectiveID.getIdentifier();
7229 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007230 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007231 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007232 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00007233 else if (IDVal == ".arm")
7234 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007235 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007236 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007237 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007238 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007239 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007240 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00007241 else if (IDVal == ".unreq")
7242 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kim135d2442011-12-20 17:38:12 +00007243 else if (IDVal == ".arch")
7244 return parseDirectiveArch(DirectiveID.getLoc());
7245 else if (IDVal == ".eabi_attribute")
7246 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00007247 return true;
7248}
7249
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007250/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00007251/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007252bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00007253 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7254 for (;;) {
7255 const MCExpr *Value;
7256 if (getParser().ParseExpression(Value))
7257 return true;
7258
Chris Lattnerc35681b2010-01-19 19:46:13 +00007259 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00007260
7261 if (getLexer().is(AsmToken::EndOfStatement))
7262 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00007263
Kevin Enderbyccab3172009-09-15 00:27:25 +00007264 // FIXME: Improve diagnostic.
7265 if (getLexer().isNot(AsmToken::Comma))
7266 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007267 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007268 }
7269 }
7270
Sean Callanana83fd7d2010-01-19 20:27:46 +00007271 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007272 return false;
7273}
7274
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007275/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00007276/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007277bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00007278 if (getLexer().isNot(AsmToken::EndOfStatement))
7279 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007280 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007281
Jim Grosbach7f882392011-12-07 18:04:19 +00007282 if (!isThumb())
7283 SwitchMode();
7284 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7285 return false;
7286}
7287
7288/// parseDirectiveARM
7289/// ::= .arm
7290bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7291 if (getLexer().isNot(AsmToken::EndOfStatement))
7292 return Error(L, "unexpected token in directive");
7293 Parser.Lex();
7294
7295 if (isThumb())
7296 SwitchMode();
7297 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00007298 return false;
7299}
7300
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007301/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00007302/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007303bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007304 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7305 bool isMachO = MAI.hasSubsectionsViaSymbols();
7306 StringRef Name;
Jim Grosbach1152cc02011-12-21 22:30:16 +00007307 bool needFuncName = true;
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007308
Jim Grosbach1152cc02011-12-21 22:30:16 +00007309 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007310 // ELF doesn't
7311 if (isMachO) {
7312 const AsmToken &Tok = Parser.getTok();
Jim Grosbach1152cc02011-12-21 22:30:16 +00007313 if (Tok.isNot(AsmToken::EndOfStatement)) {
7314 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7315 return Error(L, "unexpected token in .thumb_func directive");
7316 Name = Tok.getIdentifier();
7317 Parser.Lex(); // Consume the identifier token.
7318 needFuncName = false;
7319 }
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007320 }
7321
Jim Grosbach1152cc02011-12-21 22:30:16 +00007322 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00007323 return Error(L, "unexpected token in directive");
Jim Grosbach1152cc02011-12-21 22:30:16 +00007324
7325 // Eat the end of statement and any blank lines that follow.
7326 while (getLexer().is(AsmToken::EndOfStatement))
7327 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007328
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007329 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbach1152cc02011-12-21 22:30:16 +00007330 // We really should be checking the next symbol definition even if there's
7331 // stuff in between.
7332 if (needFuncName) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00007333 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007334 }
7335
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00007336 // Mark symbol as a thumb symbol.
7337 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7338 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00007339 return false;
7340}
7341
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007342/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00007343/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007344bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00007345 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007346 if (Tok.isNot(AsmToken::Identifier))
7347 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00007348 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00007349 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00007350 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00007351 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00007352 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00007353 else
7354 return Error(L, "unrecognized syntax mode in .syntax directive");
7355
7356 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00007357 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007358 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007359
7360 // TODO tell the MC streamer the mode
7361 // getParser().getStreamer().Emit???();
7362 return false;
7363}
7364
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007365/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00007366/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007367bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00007368 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007369 if (Tok.isNot(AsmToken::Integer))
7370 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00007371 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00007372 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00007373 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00007374 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00007375 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007376 else
7377 return Error(L, "invalid operand to .code directive");
7378
7379 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00007380 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007381 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007382
Evan Cheng284b4672011-07-08 22:36:29 +00007383 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00007384 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00007385 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00007386 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00007387 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00007388 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00007389 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00007390 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00007391 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00007392
Kevin Enderby146dcf22009-10-15 20:48:48 +00007393 return false;
7394}
7395
Jim Grosbachab5830e2011-12-14 02:16:11 +00007396/// parseDirectiveReq
7397/// ::= name .req registername
7398bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7399 Parser.Lex(); // Eat the '.req' token.
7400 unsigned Reg;
7401 SMLoc SRegLoc, ERegLoc;
7402 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7403 Parser.EatToEndOfStatement();
7404 return Error(SRegLoc, "register name expected");
7405 }
7406
7407 // Shouldn't be anything else.
7408 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7409 Parser.EatToEndOfStatement();
7410 return Error(Parser.getTok().getLoc(),
7411 "unexpected input in .req directive.");
7412 }
7413
7414 Parser.Lex(); // Consume the EndOfStatement
7415
7416 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7417 return Error(SRegLoc, "redefinition of '" + Name +
7418 "' does not match original.");
7419
7420 return false;
7421}
7422
7423/// parseDirectiveUneq
7424/// ::= .unreq registername
7425bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7426 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7427 Parser.EatToEndOfStatement();
7428 return Error(L, "unexpected input in .unreq directive.");
7429 }
7430 RegisterReqs.erase(Parser.getTok().getIdentifier());
7431 Parser.Lex(); // Eat the identifier.
7432 return false;
7433}
7434
Jason W Kim135d2442011-12-20 17:38:12 +00007435/// parseDirectiveArch
7436/// ::= .arch token
7437bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7438 return true;
7439}
7440
7441/// parseDirectiveEabiAttr
7442/// ::= .eabi_attribute int, int
7443bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7444 return true;
7445}
7446
Sean Callanan643a5572010-04-07 20:29:34 +00007447extern "C" void LLVMInitializeARMAsmLexer();
7448
Kevin Enderby8be42bd2009-10-30 22:55:57 +00007449/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00007450extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00007451 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7452 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00007453 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007454}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00007455
Chris Lattner3e4582a2010-09-06 19:11:01 +00007456#define GET_REGISTER_MATCHER
7457#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00007458#include "ARMGenAsmMatcher.inc"