blob: fcb85449e63e5e9bf4079f9d9f9e3b70d177d6f3 [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 Grosbach118b38c2011-10-21 22:21:10 +00001104 bool isVecListTwoQ() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001105 if (!isDoubleSpacedVectorList()) return false;
1106 return VectorList.Count == 2;
Jim Grosbach118b38c2011-10-21 22:21:10 +00001107 }
1108
Jim Grosbache5307f92012-03-05 21:43:40 +00001109 bool isVecListDPairSpaced() const {
1110 if (!isSingleSpacedVectorList()) return false;
1111 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1112 .contains(VectorList.RegNum));
1113 }
1114
Jim Grosbachac2af3f2012-01-23 23:20:46 +00001115 bool isVecListThreeQ() const {
1116 if (!isDoubleSpacedVectorList()) return false;
1117 return VectorList.Count == 3;
1118 }
1119
Jim Grosbach1e946a42012-01-24 00:43:12 +00001120 bool isVecListFourQ() const {
1121 if (!isDoubleSpacedVectorList()) return false;
1122 return VectorList.Count == 4;
1123 }
1124
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001125 bool isSingleSpacedVectorAllLanes() const {
1126 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1127 }
1128 bool isDoubleSpacedVectorAllLanes() const {
1129 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1130 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001131 bool isVecListOneDAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001132 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001133 return VectorList.Count == 1;
1134 }
1135
Jim Grosbach13a292c2012-03-06 22:01:44 +00001136 bool isVecListDPairAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001137 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach13a292c2012-03-06 22:01:44 +00001138 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1139 .contains(VectorList.RegNum));
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001140 }
1141
1142 bool isVecListTwoQAllLanes() const {
1143 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001144 return VectorList.Count == 2;
1145 }
1146
Jim Grosbachb78403c2012-01-24 23:47:04 +00001147 bool isVecListThreeDAllLanes() const {
1148 if (!isSingleSpacedVectorAllLanes()) return false;
1149 return VectorList.Count == 3;
1150 }
1151
1152 bool isVecListThreeQAllLanes() const {
1153 if (!isDoubleSpacedVectorAllLanes()) return false;
1154 return VectorList.Count == 3;
1155 }
1156
Jim Grosbach086cbfa2012-01-25 00:01:08 +00001157 bool isVecListFourDAllLanes() const {
1158 if (!isSingleSpacedVectorAllLanes()) return false;
1159 return VectorList.Count == 4;
1160 }
1161
1162 bool isVecListFourQAllLanes() const {
1163 if (!isDoubleSpacedVectorAllLanes()) return false;
1164 return VectorList.Count == 4;
1165 }
1166
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001167 bool isSingleSpacedVectorIndexed() const {
1168 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1169 }
1170 bool isDoubleSpacedVectorIndexed() const {
1171 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1172 }
Jim Grosbach04945c42011-12-02 00:35:16 +00001173 bool isVecListOneDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001174 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach04945c42011-12-02 00:35:16 +00001175 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1176 }
1177
Jim Grosbachda511042011-12-14 23:35:06 +00001178 bool isVecListOneDHWordIndexed() 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 <= 3;
1181 }
1182
1183 bool isVecListOneDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001184 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001185 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1186 }
1187
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001188 bool isVecListTwoDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001189 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001190 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1191 }
1192
Jim Grosbachda511042011-12-14 23:35:06 +00001193 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001194 if (!isSingleSpacedVectorIndexed()) return false;
1195 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1196 }
1197
1198 bool isVecListTwoQWordIndexed() const {
1199 if (!isDoubleSpacedVectorIndexed()) return false;
1200 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1201 }
1202
1203 bool isVecListTwoQHWordIndexed() const {
1204 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001205 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1206 }
1207
1208 bool isVecListTwoDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001209 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001210 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1211 }
1212
Jim Grosbacha8b444b2012-01-23 21:53:26 +00001213 bool isVecListThreeDByteIndexed() const {
1214 if (!isSingleSpacedVectorIndexed()) return false;
1215 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1216 }
1217
1218 bool isVecListThreeDHWordIndexed() const {
1219 if (!isSingleSpacedVectorIndexed()) return false;
1220 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1221 }
1222
1223 bool isVecListThreeQWordIndexed() const {
1224 if (!isDoubleSpacedVectorIndexed()) return false;
1225 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1226 }
1227
1228 bool isVecListThreeQHWordIndexed() const {
1229 if (!isDoubleSpacedVectorIndexed()) return false;
1230 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1231 }
1232
1233 bool isVecListThreeDWordIndexed() const {
1234 if (!isSingleSpacedVectorIndexed()) return false;
1235 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1236 }
1237
Jim Grosbach14952a02012-01-24 18:37:25 +00001238 bool isVecListFourDByteIndexed() const {
1239 if (!isSingleSpacedVectorIndexed()) return false;
1240 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1241 }
1242
1243 bool isVecListFourDHWordIndexed() const {
1244 if (!isSingleSpacedVectorIndexed()) return false;
1245 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1246 }
1247
1248 bool isVecListFourQWordIndexed() const {
1249 if (!isDoubleSpacedVectorIndexed()) return false;
1250 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1251 }
1252
1253 bool isVecListFourQHWordIndexed() const {
1254 if (!isDoubleSpacedVectorIndexed()) return false;
1255 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1256 }
1257
1258 bool isVecListFourDWordIndexed() const {
1259 if (!isSingleSpacedVectorIndexed()) return false;
1260 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1261 }
1262
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001263 bool isVectorIndex8() const {
1264 if (Kind != k_VectorIndex) return false;
1265 return VectorIndex.Val < 8;
1266 }
1267 bool isVectorIndex16() const {
1268 if (Kind != k_VectorIndex) return false;
1269 return VectorIndex.Val < 4;
1270 }
1271 bool isVectorIndex32() const {
1272 if (Kind != k_VectorIndex) return false;
1273 return VectorIndex.Val < 2;
1274 }
1275
Jim Grosbach741cd732011-10-17 22:26:03 +00001276 bool isNEONi8splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001277 if (!isImm()) return false;
Jim Grosbach741cd732011-10-17 22:26:03 +00001278 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1279 // Must be a constant.
1280 if (!CE) return false;
1281 int64_t Value = CE->getValue();
1282 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1283 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001284 return Value >= 0 && Value < 256;
1285 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001286
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001287 bool isNEONi16splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001288 if (!isImm()) return false;
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001289 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1290 // Must be a constant.
1291 if (!CE) return false;
1292 int64_t Value = CE->getValue();
1293 // i16 value in the range [0,255] or [0x0100, 0xff00]
1294 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1295 }
1296
Jim Grosbach8211c052011-10-18 00:22:00 +00001297 bool isNEONi32splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001298 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001299 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1300 // Must be a constant.
1301 if (!CE) return false;
1302 int64_t Value = CE->getValue();
1303 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1304 return (Value >= 0 && Value < 256) ||
1305 (Value >= 0x0100 && Value <= 0xff00) ||
1306 (Value >= 0x010000 && Value <= 0xff0000) ||
1307 (Value >= 0x01000000 && Value <= 0xff000000);
1308 }
1309
1310 bool isNEONi32vmov() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001311 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001312 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1313 // Must be a constant.
1314 if (!CE) return false;
1315 int64_t Value = CE->getValue();
1316 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1317 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1318 return (Value >= 0 && Value < 256) ||
1319 (Value >= 0x0100 && Value <= 0xff00) ||
1320 (Value >= 0x010000 && Value <= 0xff0000) ||
1321 (Value >= 0x01000000 && Value <= 0xff000000) ||
1322 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1323 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1324 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00001325 bool isNEONi32vmovNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001326 if (!isImm()) return false;
Jim Grosbach045b6c72011-12-19 23:51:07 +00001327 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1328 // Must be a constant.
1329 if (!CE) return false;
1330 int64_t Value = ~CE->getValue();
1331 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1332 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1333 return (Value >= 0 && Value < 256) ||
1334 (Value >= 0x0100 && Value <= 0xff00) ||
1335 (Value >= 0x010000 && Value <= 0xff0000) ||
1336 (Value >= 0x01000000 && Value <= 0xff000000) ||
1337 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1338 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1339 }
Jim Grosbach8211c052011-10-18 00:22:00 +00001340
Jim Grosbache4454e02011-10-18 16:18:11 +00001341 bool isNEONi64splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001342 if (!isImm()) return false;
Jim Grosbache4454e02011-10-18 16:18:11 +00001343 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1344 // Must be a constant.
1345 if (!CE) return false;
1346 uint64_t Value = CE->getValue();
1347 // i64 value with each byte being either 0 or 0xff.
1348 for (unsigned i = 0; i < 8; ++i)
1349 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1350 return true;
1351 }
1352
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001353 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001354 // Add as immediates when possible. Null MCExpr = 0.
1355 if (Expr == 0)
1356 Inst.addOperand(MCOperand::CreateImm(0));
1357 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001358 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1359 else
1360 Inst.addOperand(MCOperand::CreateExpr(Expr));
1361 }
1362
Daniel Dunbard8042b72010-08-11 06:36:53 +00001363 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001364 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001365 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001366 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1367 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001368 }
1369
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001370 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
1372 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1373 }
1374
Jim Grosbach48399582011-10-12 17:34:41 +00001375 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1376 assert(N == 1 && "Invalid number of operands!");
1377 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1378 }
1379
1380 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
1382 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1383 }
1384
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001385 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1388 }
1389
1390 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
1392 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1393 }
1394
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001395 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1396 assert(N == 1 && "Invalid number of operands!");
1397 Inst.addOperand(MCOperand::CreateReg(getReg()));
1398 }
1399
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001400 void addRegOperands(MCInst &Inst, unsigned N) const {
1401 assert(N == 1 && "Invalid number of operands!");
1402 Inst.addOperand(MCOperand::CreateReg(getReg()));
1403 }
1404
Jim Grosbachac798e12011-07-25 20:49:51 +00001405 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001406 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001407 assert(isRegShiftedReg() &&
1408 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001409 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1410 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001411 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001412 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001413 }
1414
Jim Grosbachac798e12011-07-25 20:49:51 +00001415 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001416 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001417 assert(isRegShiftedImm() &&
1418 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001419 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001420 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001421 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001422 }
1423
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001424 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001425 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001426 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1427 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001428 }
1429
Bill Wendling8d2aa032010-11-08 23:49:57 +00001430 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001431 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001432 const SmallVectorImpl<unsigned> &RegList = getRegList();
1433 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001434 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1435 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001436 }
1437
Bill Wendling9898ac92010-11-17 04:32:08 +00001438 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1439 addRegListOperands(Inst, N);
1440 }
1441
1442 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1443 addRegListOperands(Inst, N);
1444 }
1445
Jim Grosbach833b9d32011-07-27 20:15:40 +00001446 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1447 assert(N == 1 && "Invalid number of operands!");
1448 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1449 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1450 }
1451
Jim Grosbach864b6092011-07-28 21:34:26 +00001452 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1453 assert(N == 1 && "Invalid number of operands!");
1454 // Munge the lsb/width into a bitfield mask.
1455 unsigned lsb = Bitfield.LSB;
1456 unsigned width = Bitfield.Width;
1457 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1458 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1459 (32 - (lsb + width)));
1460 Inst.addOperand(MCOperand::CreateImm(Mask));
1461 }
1462
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001463 void addImmOperands(MCInst &Inst, unsigned N) const {
1464 assert(N == 1 && "Invalid number of operands!");
1465 addExpr(Inst, getImm());
1466 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001467
Jim Grosbachea231912011-12-22 22:19:05 +00001468 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1469 assert(N == 1 && "Invalid number of operands!");
1470 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1471 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1472 }
1473
1474 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1475 assert(N == 1 && "Invalid number of operands!");
1476 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1477 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1478 }
1479
Jim Grosbache7fbce72011-10-03 23:38:36 +00001480 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00001482 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1483 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1484 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbache7fbce72011-10-03 23:38:36 +00001485 }
1486
Jim Grosbach7db8d692011-09-08 22:07:06 +00001487 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
1489 // FIXME: We really want to scale the value here, but the LDRD/STRD
1490 // instruction don't encode operands that way yet.
1491 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1492 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1493 }
1494
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001495 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497 // The immediate is scaled by four in the encoding and is stored
1498 // in the MCInst as such. Lop off the low two bits here.
1499 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1500 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1501 }
1502
1503 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1504 assert(N == 1 && "Invalid number of operands!");
1505 // The immediate is scaled by four in the encoding and is stored
1506 // in the MCInst as such. Lop off the low two bits here.
1507 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1508 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1509 }
1510
Jim Grosbach475c6db2011-07-25 23:09:14 +00001511 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1512 assert(N == 1 && "Invalid number of operands!");
1513 // The constant encodes as the immediate-1, and we store in the instruction
1514 // the bits as encoded, so subtract off one here.
1515 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1516 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1517 }
1518
Jim Grosbach801e0a32011-07-22 23:16:18 +00001519 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1520 assert(N == 1 && "Invalid number of operands!");
1521 // The constant encodes as the immediate-1, and we store in the instruction
1522 // the bits as encoded, so subtract off one here.
1523 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1524 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1525 }
1526
Jim Grosbach46dd4132011-08-17 21:51:27 +00001527 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1528 assert(N == 1 && "Invalid number of operands!");
1529 // The constant encodes as the immediate, except for 32, which encodes as
1530 // zero.
1531 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1532 unsigned Imm = CE->getValue();
1533 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1534 }
1535
Jim Grosbach27c1e252011-07-21 17:23:04 +00001536 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1537 assert(N == 1 && "Invalid number of operands!");
1538 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1539 // the instruction as well.
1540 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1541 int Val = CE->getValue();
1542 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1543 }
1544
Jim Grosbachb009a872011-10-28 22:36:30 +00001545 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1546 assert(N == 1 && "Invalid number of operands!");
1547 // The operand is actually a t2_so_imm, but we have its bitwise
1548 // negation in the assembly source, so twiddle it here.
1549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1550 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1551 }
1552
Jim Grosbach30506252011-12-08 00:31:07 +00001553 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1554 assert(N == 1 && "Invalid number of operands!");
1555 // The operand is actually a t2_so_imm, but we have its
1556 // negation in the assembly source, so twiddle it here.
1557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1558 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1559 }
1560
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001561 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1562 assert(N == 1 && "Invalid number of operands!");
1563 // The operand is actually a so_imm, but we have its bitwise
1564 // negation in the assembly source, so twiddle it here.
1565 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1566 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1567 }
1568
Jim Grosbach30506252011-12-08 00:31:07 +00001569 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1570 assert(N == 1 && "Invalid number of operands!");
1571 // The operand is actually a so_imm, but we have its
1572 // negation in the assembly source, so twiddle it here.
1573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1574 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1575 }
1576
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001577 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
1579 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1580 }
1581
Jim Grosbachd3595712011-08-03 23:50:40 +00001582 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001584 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001585 }
1586
Jim Grosbach94298a92012-01-18 22:46:46 +00001587 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589 int32_t Imm = Memory.OffsetImm->getValue();
1590 // FIXME: Handle #-0
1591 if (Imm == INT32_MIN) Imm = 0;
1592 Inst.addOperand(MCOperand::CreateImm(Imm));
1593 }
1594
Jim Grosbacha95ec992011-10-11 17:29:55 +00001595 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1596 assert(N == 2 && "Invalid number of operands!");
1597 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1598 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1599 }
1600
Jim Grosbachd3595712011-08-03 23:50:40 +00001601 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1602 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001603 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1604 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001605 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1606 // Special case for #-0
1607 if (Val == INT32_MIN) Val = 0;
1608 if (Val < 0) Val = -Val;
1609 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1610 } else {
1611 // For register offset, we encode the shift type and negation flag
1612 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001613 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1614 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001615 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001616 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1617 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001618 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001619 }
1620
Jim Grosbachcd17c122011-08-04 23:01:30 +00001621 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1622 assert(N == 2 && "Invalid number of operands!");
1623 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1624 assert(CE && "non-constant AM2OffsetImm operand!");
1625 int32_t Val = CE->getValue();
1626 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1627 // Special case for #-0
1628 if (Val == INT32_MIN) Val = 0;
1629 if (Val < 0) Val = -Val;
1630 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1631 Inst.addOperand(MCOperand::CreateReg(0));
1632 Inst.addOperand(MCOperand::CreateImm(Val));
1633 }
1634
Jim Grosbach5b96b802011-08-10 20:29:19 +00001635 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1636 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001637 // If we have an immediate that's not a constant, treat it as a label
1638 // reference needing a fixup. If it is a constant, it's something else
1639 // and we reject it.
1640 if (isImm()) {
1641 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1642 Inst.addOperand(MCOperand::CreateReg(0));
1643 Inst.addOperand(MCOperand::CreateImm(0));
1644 return;
1645 }
1646
Jim Grosbach871dff72011-10-11 15:59:20 +00001647 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1648 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001649 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1650 // Special case for #-0
1651 if (Val == INT32_MIN) Val = 0;
1652 if (Val < 0) Val = -Val;
1653 Val = ARM_AM::getAM3Opc(AddSub, Val);
1654 } else {
1655 // For register offset, we encode the shift type and negation flag
1656 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001657 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001658 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001659 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1660 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001661 Inst.addOperand(MCOperand::CreateImm(Val));
1662 }
1663
1664 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1665 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001666 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001667 int32_t Val =
1668 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1669 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1670 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001671 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001672 }
1673
1674 // Constant offset.
1675 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1676 int32_t Val = CE->getValue();
1677 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1678 // Special case for #-0
1679 if (Val == INT32_MIN) Val = 0;
1680 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001681 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001682 Inst.addOperand(MCOperand::CreateReg(0));
1683 Inst.addOperand(MCOperand::CreateImm(Val));
1684 }
1685
Jim Grosbachd3595712011-08-03 23:50:40 +00001686 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1687 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001688 // If we have an immediate that's not a constant, treat it as a label
1689 // reference needing a fixup. If it is a constant, it's something else
1690 // and we reject it.
1691 if (isImm()) {
1692 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1693 Inst.addOperand(MCOperand::CreateImm(0));
1694 return;
1695 }
1696
Jim Grosbachd3595712011-08-03 23:50:40 +00001697 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001698 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001699 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1700 // Special case for #-0
1701 if (Val == INT32_MIN) Val = 0;
1702 if (Val < 0) Val = -Val;
1703 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001704 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001705 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001706 }
1707
Jim Grosbach7db8d692011-09-08 22:07:06 +00001708 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1709 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001710 // If we have an immediate that's not a constant, treat it as a label
1711 // reference needing a fixup. If it is a constant, it's something else
1712 // and we reject it.
1713 if (isImm()) {
1714 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1715 Inst.addOperand(MCOperand::CreateImm(0));
1716 return;
1717 }
1718
Jim Grosbach871dff72011-10-11 15:59:20 +00001719 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1720 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001721 Inst.addOperand(MCOperand::CreateImm(Val));
1722 }
1723
Jim Grosbacha05627e2011-09-09 18:37:27 +00001724 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1725 assert(N == 2 && "Invalid number of operands!");
1726 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001727 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1728 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001729 Inst.addOperand(MCOperand::CreateImm(Val));
1730 }
1731
Jim Grosbachd3595712011-08-03 23:50:40 +00001732 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1733 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001734 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1735 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001736 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001737 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001738
Jim Grosbach2392c532011-09-07 23:39:14 +00001739 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1740 addMemImm8OffsetOperands(Inst, N);
1741 }
1742
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001743 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001744 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001745 }
1746
1747 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1748 assert(N == 2 && "Invalid number of operands!");
1749 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001750 if (isImm()) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001751 addExpr(Inst, getImm());
1752 Inst.addOperand(MCOperand::CreateImm(0));
1753 return;
1754 }
1755
1756 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001757 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1758 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001759 Inst.addOperand(MCOperand::CreateImm(Val));
1760 }
1761
Jim Grosbachd3595712011-08-03 23:50:40 +00001762 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1763 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001764 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001765 if (isImm()) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001766 addExpr(Inst, getImm());
1767 Inst.addOperand(MCOperand::CreateImm(0));
1768 return;
1769 }
1770
1771 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001772 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1773 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001774 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001775 }
Bill Wendling811c9362010-11-30 07:44:32 +00001776
Jim Grosbach05541f42011-09-19 22:21:13 +00001777 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1778 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001779 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1780 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001781 }
1782
1783 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1784 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001785 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1786 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001787 }
1788
Jim Grosbachd3595712011-08-03 23:50:40 +00001789 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1790 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001791 unsigned Val =
1792 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1793 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001794 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1795 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001796 Inst.addOperand(MCOperand::CreateImm(Val));
1797 }
1798
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001799 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1800 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001801 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1802 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1803 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001804 }
1805
Jim Grosbachd3595712011-08-03 23:50:40 +00001806 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1807 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001808 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1809 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001810 }
1811
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001812 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1813 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001814 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1815 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001816 Inst.addOperand(MCOperand::CreateImm(Val));
1817 }
1818
Jim Grosbach26d35872011-08-19 18:55:51 +00001819 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1820 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001821 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1822 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001823 Inst.addOperand(MCOperand::CreateImm(Val));
1824 }
1825
Jim Grosbacha32c7532011-08-19 18:49:59 +00001826 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1827 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001828 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1829 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001830 Inst.addOperand(MCOperand::CreateImm(Val));
1831 }
1832
Jim Grosbach23983d62011-08-19 18:13:48 +00001833 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1834 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001835 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1836 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001837 Inst.addOperand(MCOperand::CreateImm(Val));
1838 }
1839
Jim Grosbachd3595712011-08-03 23:50:40 +00001840 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1841 assert(N == 1 && "Invalid number of operands!");
1842 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1843 assert(CE && "non-constant post-idx-imm8 operand!");
1844 int Imm = CE->getValue();
1845 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001846 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001847 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1848 Inst.addOperand(MCOperand::CreateImm(Imm));
1849 }
1850
Jim Grosbach93981412011-10-11 21:55:36 +00001851 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1852 assert(N == 1 && "Invalid number of operands!");
1853 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1854 assert(CE && "non-constant post-idx-imm8s4 operand!");
1855 int Imm = CE->getValue();
1856 bool isAdd = Imm >= 0;
1857 if (Imm == INT32_MIN) Imm = 0;
1858 // Immediate is scaled by 4.
1859 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1860 Inst.addOperand(MCOperand::CreateImm(Imm));
1861 }
1862
Jim Grosbachd3595712011-08-03 23:50:40 +00001863 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1864 assert(N == 2 && "Invalid number of operands!");
1865 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001866 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1867 }
1868
1869 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1870 assert(N == 2 && "Invalid number of operands!");
1871 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1872 // The sign, shift type, and shift amount are encoded in a single operand
1873 // using the AM2 encoding helpers.
1874 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1875 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1876 PostIdxReg.ShiftTy);
1877 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001878 }
1879
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001880 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1881 assert(N == 1 && "Invalid number of operands!");
1882 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1883 }
1884
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001885 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1886 assert(N == 1 && "Invalid number of operands!");
1887 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1888 }
1889
Jim Grosbach182b6a02011-11-29 23:51:09 +00001890 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001891 assert(N == 1 && "Invalid number of operands!");
1892 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1893 }
1894
Jim Grosbach04945c42011-12-02 00:35:16 +00001895 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1896 assert(N == 2 && "Invalid number of operands!");
1897 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1898 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1899 }
1900
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001901 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1902 assert(N == 1 && "Invalid number of operands!");
1903 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1904 }
1905
1906 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1907 assert(N == 1 && "Invalid number of operands!");
1908 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1909 }
1910
1911 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1912 assert(N == 1 && "Invalid number of operands!");
1913 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1914 }
1915
Jim Grosbach741cd732011-10-17 22:26:03 +00001916 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1917 assert(N == 1 && "Invalid number of operands!");
1918 // The immediate encodes the type of constant as well as the value.
1919 // Mask in that this is an i8 splat.
1920 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1921 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1922 }
1923
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001924 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1925 assert(N == 1 && "Invalid number of operands!");
1926 // The immediate encodes the type of constant as well as the value.
1927 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1928 unsigned Value = CE->getValue();
1929 if (Value >= 256)
1930 Value = (Value >> 8) | 0xa00;
1931 else
1932 Value |= 0x800;
1933 Inst.addOperand(MCOperand::CreateImm(Value));
1934 }
1935
Jim Grosbach8211c052011-10-18 00:22:00 +00001936 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1937 assert(N == 1 && "Invalid number of operands!");
1938 // The immediate encodes the type of constant as well as the value.
1939 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1940 unsigned Value = CE->getValue();
1941 if (Value >= 256 && Value <= 0xff00)
1942 Value = (Value >> 8) | 0x200;
1943 else if (Value > 0xffff && Value <= 0xff0000)
1944 Value = (Value >> 16) | 0x400;
1945 else if (Value > 0xffffff)
1946 Value = (Value >> 24) | 0x600;
1947 Inst.addOperand(MCOperand::CreateImm(Value));
1948 }
1949
1950 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1951 assert(N == 1 && "Invalid number of operands!");
1952 // The immediate encodes the type of constant as well as the value.
1953 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1954 unsigned Value = CE->getValue();
1955 if (Value >= 256 && Value <= 0xffff)
1956 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1957 else if (Value > 0xffff && Value <= 0xffffff)
1958 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1959 else if (Value > 0xffffff)
1960 Value = (Value >> 24) | 0x600;
1961 Inst.addOperand(MCOperand::CreateImm(Value));
1962 }
1963
Jim Grosbach045b6c72011-12-19 23:51:07 +00001964 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1965 assert(N == 1 && "Invalid number of operands!");
1966 // The immediate encodes the type of constant as well as the value.
1967 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1968 unsigned Value = ~CE->getValue();
1969 if (Value >= 256 && Value <= 0xffff)
1970 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1971 else if (Value > 0xffff && Value <= 0xffffff)
1972 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1973 else if (Value > 0xffffff)
1974 Value = (Value >> 24) | 0x600;
1975 Inst.addOperand(MCOperand::CreateImm(Value));
1976 }
1977
Jim Grosbache4454e02011-10-18 16:18:11 +00001978 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1979 assert(N == 1 && "Invalid number of operands!");
1980 // The immediate encodes the type of constant as well as the value.
1981 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1982 uint64_t Value = CE->getValue();
1983 unsigned Imm = 0;
1984 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1985 Imm |= (Value & 1) << i;
1986 }
1987 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1988 }
1989
Jim Grosbach602aa902011-07-13 15:34:57 +00001990 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001991
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001992 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001993 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001994 Op->ITMask.Mask = Mask;
1995 Op->StartLoc = S;
1996 Op->EndLoc = S;
1997 return Op;
1998 }
1999
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002000 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002001 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00002002 Op->CC.Val = CC;
2003 Op->StartLoc = S;
2004 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002005 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00002006 }
2007
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002008 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002009 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002010 Op->Cop.Val = CopVal;
2011 Op->StartLoc = S;
2012 Op->EndLoc = S;
2013 return Op;
2014 }
2015
2016 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002017 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002018 Op->Cop.Val = CopVal;
2019 Op->StartLoc = S;
2020 Op->EndLoc = S;
2021 return Op;
2022 }
2023
Jim Grosbach48399582011-10-12 17:34:41 +00002024 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2025 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2026 Op->Cop.Val = Val;
2027 Op->StartLoc = S;
2028 Op->EndLoc = E;
2029 return Op;
2030 }
2031
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002032 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002033 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002034 Op->Reg.RegNum = RegNum;
2035 Op->StartLoc = S;
2036 Op->EndLoc = S;
2037 return Op;
2038 }
2039
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002040 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002041 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002042 Op->Tok.Data = Str.data();
2043 Op->Tok.Length = Str.size();
2044 Op->StartLoc = S;
2045 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002046 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002047 }
2048
Bill Wendling2063b842010-11-18 23:43:05 +00002049 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002050 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002051 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002052 Op->StartLoc = S;
2053 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002054 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002055 }
2056
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002057 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2058 unsigned SrcReg,
2059 unsigned ShiftReg,
2060 unsigned ShiftImm,
2061 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002062 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00002063 Op->RegShiftedReg.ShiftTy = ShTy;
2064 Op->RegShiftedReg.SrcReg = SrcReg;
2065 Op->RegShiftedReg.ShiftReg = ShiftReg;
2066 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002067 Op->StartLoc = S;
2068 Op->EndLoc = E;
2069 return Op;
2070 }
2071
Owen Andersonb595ed02011-07-21 18:54:16 +00002072 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2073 unsigned SrcReg,
2074 unsigned ShiftImm,
2075 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002076 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00002077 Op->RegShiftedImm.ShiftTy = ShTy;
2078 Op->RegShiftedImm.SrcReg = SrcReg;
2079 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00002080 Op->StartLoc = S;
2081 Op->EndLoc = E;
2082 return Op;
2083 }
2084
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002085 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002086 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002087 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002088 Op->ShifterImm.isASR = isASR;
2089 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002090 Op->StartLoc = S;
2091 Op->EndLoc = E;
2092 return Op;
2093 }
2094
Jim Grosbach833b9d32011-07-27 20:15:40 +00002095 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002096 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00002097 Op->RotImm.Imm = Imm;
2098 Op->StartLoc = S;
2099 Op->EndLoc = E;
2100 return Op;
2101 }
2102
Jim Grosbach864b6092011-07-28 21:34:26 +00002103 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2104 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002105 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00002106 Op->Bitfield.LSB = LSB;
2107 Op->Bitfield.Width = Width;
2108 Op->StartLoc = S;
2109 Op->EndLoc = E;
2110 return Op;
2111 }
2112
Bill Wendling2cae3272010-11-09 22:44:22 +00002113 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00002114 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002115 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002116 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002117
Jim Grosbach75461af2011-09-13 22:56:44 +00002118 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002119 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00002120 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00002121 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002122 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002123
2124 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00002125 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002126 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00002127 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00002128 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002129 Op->StartLoc = StartLoc;
2130 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00002131 return Op;
2132 }
2133
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002134 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach2f50e922011-12-15 21:44:33 +00002135 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002136 ARMOperand *Op = new ARMOperand(k_VectorList);
2137 Op->VectorList.RegNum = RegNum;
2138 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002139 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002140 Op->StartLoc = S;
2141 Op->EndLoc = E;
2142 return Op;
2143 }
2144
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002145 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002146 bool isDoubleSpaced,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002147 SMLoc S, SMLoc E) {
2148 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2149 Op->VectorList.RegNum = RegNum;
2150 Op->VectorList.Count = Count;
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002151 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002152 Op->StartLoc = S;
2153 Op->EndLoc = E;
2154 return Op;
2155 }
2156
Jim Grosbach04945c42011-12-02 00:35:16 +00002157 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002158 unsigned Index,
2159 bool isDoubleSpaced,
2160 SMLoc S, SMLoc E) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002161 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2162 Op->VectorList.RegNum = RegNum;
2163 Op->VectorList.Count = Count;
2164 Op->VectorList.LaneIndex = Index;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002165 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach04945c42011-12-02 00:35:16 +00002166 Op->StartLoc = S;
2167 Op->EndLoc = E;
2168 return Op;
2169 }
2170
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002171 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2172 MCContext &Ctx) {
2173 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2174 Op->VectorIndex.Val = Idx;
2175 Op->StartLoc = S;
2176 Op->EndLoc = E;
2177 return Op;
2178 }
2179
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002180 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002181 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002182 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002183 Op->StartLoc = S;
2184 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002185 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002186 }
2187
Jim Grosbachd3595712011-08-03 23:50:40 +00002188 static ARMOperand *CreateMem(unsigned BaseRegNum,
2189 const MCConstantExpr *OffsetImm,
2190 unsigned OffsetRegNum,
2191 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002192 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002193 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002194 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002195 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002196 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002197 Op->Memory.BaseRegNum = BaseRegNum;
2198 Op->Memory.OffsetImm = OffsetImm;
2199 Op->Memory.OffsetRegNum = OffsetRegNum;
2200 Op->Memory.ShiftType = ShiftType;
2201 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002202 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002203 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002204 Op->StartLoc = S;
2205 Op->EndLoc = E;
2206 return Op;
2207 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002208
Jim Grosbachc320c852011-08-05 21:28:30 +00002209 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2210 ARM_AM::ShiftOpc ShiftTy,
2211 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002212 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002213 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002214 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002215 Op->PostIdxReg.isAdd = isAdd;
2216 Op->PostIdxReg.ShiftTy = ShiftTy;
2217 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002218 Op->StartLoc = S;
2219 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002220 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002221 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002222
2223 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002224 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002225 Op->MBOpt.Val = Opt;
2226 Op->StartLoc = S;
2227 Op->EndLoc = S;
2228 return Op;
2229 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002230
2231 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002232 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002233 Op->IFlags.Val = IFlags;
2234 Op->StartLoc = S;
2235 Op->EndLoc = S;
2236 return Op;
2237 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002238
2239 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002240 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002241 Op->MMask.Val = MMask;
2242 Op->StartLoc = S;
2243 Op->EndLoc = S;
2244 return Op;
2245 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002246};
2247
2248} // end anonymous namespace.
2249
Jim Grosbach602aa902011-07-13 15:34:57 +00002250void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002251 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002252 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002253 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002254 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002255 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002256 OS << "<ccout " << getReg() << ">";
2257 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002258 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002259 static const char *MaskStr[] = {
2260 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2261 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2262 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002263 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2264 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2265 break;
2266 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002267 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002268 OS << "<coprocessor number: " << getCoproc() << ">";
2269 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002270 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002271 OS << "<coprocessor register: " << getCoproc() << ">";
2272 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002273 case k_CoprocOption:
2274 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2275 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002276 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002277 OS << "<mask: " << getMSRMask() << ">";
2278 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002279 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002280 getImm()->print(OS);
2281 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002282 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002283 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2284 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002285 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002286 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002287 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002288 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002289 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002290 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002291 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2292 << PostIdxReg.RegNum;
2293 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2294 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2295 << PostIdxReg.ShiftImm;
2296 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002297 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002298 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002299 OS << "<ARM_PROC::";
2300 unsigned IFlags = getProcIFlags();
2301 for (int i=2; i >= 0; --i)
2302 if (IFlags & (1 << i))
2303 OS << ARM_PROC::IFlagsToString(1 << i);
2304 OS << ">";
2305 break;
2306 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002307 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002308 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002309 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002310 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002311 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2312 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002313 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002314 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002315 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002316 << RegShiftedReg.SrcReg << " "
2317 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2318 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002319 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002320 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002321 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002322 << RegShiftedImm.SrcReg << " "
2323 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2324 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002325 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002326 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002327 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2328 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002329 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002330 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2331 << ", width: " << Bitfield.Width << ">";
2332 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002333 case k_RegisterList:
2334 case k_DPRRegisterList:
2335 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002336 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002337
Bill Wendlingbed94652010-11-09 23:28:44 +00002338 const SmallVectorImpl<unsigned> &RegList = getRegList();
2339 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002340 I = RegList.begin(), E = RegList.end(); I != E; ) {
2341 OS << *I;
2342 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002343 }
2344
2345 OS << ">";
2346 break;
2347 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002348 case k_VectorList:
2349 OS << "<vector_list " << VectorList.Count << " * "
2350 << VectorList.RegNum << ">";
2351 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002352 case k_VectorListAllLanes:
2353 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2354 << VectorList.RegNum << ">";
2355 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002356 case k_VectorListIndexed:
2357 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2358 << VectorList.Count << " * " << VectorList.RegNum << ">";
2359 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002360 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002361 OS << "'" << getToken() << "'";
2362 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002363 case k_VectorIndex:
2364 OS << "<vectorindex " << getVectorIndex() << ">";
2365 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002366 }
2367}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002368
2369/// @name Auto-generated Match Functions
2370/// {
2371
2372static unsigned MatchRegisterName(StringRef Name);
2373
2374/// }
2375
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002376bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2377 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002378 StartLoc = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002379 RegNo = tryParseRegister();
Jim Grosbachab5830e2011-12-14 02:16:11 +00002380 EndLoc = Parser.getTok().getLoc();
Roman Divacky36b1b472011-01-27 17:14:22 +00002381
2382 return (RegNo == (unsigned)-1);
2383}
2384
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002385/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002386/// and if it is a register name the token is eaten and the register number is
2387/// returned. Otherwise return -1.
2388///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002389int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002390 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002391 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002392
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002393 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002394 unsigned RegNum = MatchRegisterName(lowerCase);
2395 if (!RegNum) {
2396 RegNum = StringSwitch<unsigned>(lowerCase)
2397 .Case("r13", ARM::SP)
2398 .Case("r14", ARM::LR)
2399 .Case("r15", ARM::PC)
2400 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002401 // Additional register name aliases for 'gas' compatibility.
2402 .Case("a1", ARM::R0)
2403 .Case("a2", ARM::R1)
2404 .Case("a3", ARM::R2)
2405 .Case("a4", ARM::R3)
2406 .Case("v1", ARM::R4)
2407 .Case("v2", ARM::R5)
2408 .Case("v3", ARM::R6)
2409 .Case("v4", ARM::R7)
2410 .Case("v5", ARM::R8)
2411 .Case("v6", ARM::R9)
2412 .Case("v7", ARM::R10)
2413 .Case("v8", ARM::R11)
2414 .Case("sb", ARM::R9)
2415 .Case("sl", ARM::R10)
2416 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002417 .Default(0);
2418 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002419 if (!RegNum) {
Jim Grosbachcd22e4a2011-12-20 23:11:00 +00002420 // Check for aliases registered via .req. Canonicalize to lower case.
2421 // That's more consistent since register names are case insensitive, and
2422 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2423 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbachab5830e2011-12-14 02:16:11 +00002424 // If no match, return failure.
2425 if (Entry == RegisterReqs.end())
2426 return -1;
2427 Parser.Lex(); // Eat identifier token.
2428 return Entry->getValue();
2429 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002430
Chris Lattner44e5981c2010-10-30 04:09:10 +00002431 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002432
Chris Lattner44e5981c2010-10-30 04:09:10 +00002433 return RegNum;
2434}
Jim Grosbach99710a82010-11-01 16:44:21 +00002435
Jim Grosbachbb24c592011-07-13 18:49:30 +00002436// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2437// If a recoverable error occurs, return 1. If an irrecoverable error
2438// occurs, return -1. An irrecoverable error is one where tokens have been
2439// consumed in the process of trying to parse the shifter (i.e., when it is
2440// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002441int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002442 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2443 SMLoc S = Parser.getTok().getLoc();
2444 const AsmToken &Tok = Parser.getTok();
2445 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2446
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002447 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002448 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002449 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002450 .Case("lsl", ARM_AM::lsl)
2451 .Case("lsr", ARM_AM::lsr)
2452 .Case("asr", ARM_AM::asr)
2453 .Case("ror", ARM_AM::ror)
2454 .Case("rrx", ARM_AM::rrx)
2455 .Default(ARM_AM::no_shift);
2456
2457 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002458 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002459
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002460 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002461
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002462 // The source register for the shift has already been added to the
2463 // operand list, so we need to pop it off and combine it into the shifted
2464 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002465 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002466 if (!PrevOp->isReg())
2467 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2468 int SrcReg = PrevOp->getReg();
2469 int64_t Imm = 0;
2470 int ShiftReg = 0;
2471 if (ShiftTy == ARM_AM::rrx) {
2472 // RRX Doesn't have an explicit shift amount. The encoder expects
2473 // the shift register to be the same as the source register. Seems odd,
2474 // but OK.
2475 ShiftReg = SrcReg;
2476 } else {
2477 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002478 if (Parser.getTok().is(AsmToken::Hash) ||
2479 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002480 Parser.Lex(); // Eat hash.
2481 SMLoc ImmLoc = Parser.getTok().getLoc();
2482 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002483 if (getParser().ParseExpression(ShiftExpr)) {
2484 Error(ImmLoc, "invalid immediate shift value");
2485 return -1;
2486 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002487 // The expression must be evaluatable as an immediate.
2488 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002489 if (!CE) {
2490 Error(ImmLoc, "invalid immediate shift value");
2491 return -1;
2492 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002493 // Range check the immediate.
2494 // lsl, ror: 0 <= imm <= 31
2495 // lsr, asr: 0 <= imm <= 32
2496 Imm = CE->getValue();
2497 if (Imm < 0 ||
2498 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2499 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002500 Error(ImmLoc, "immediate shift value out of range");
2501 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002502 }
Jim Grosbach21488b82011-12-22 17:37:00 +00002503 // shift by zero is a nop. Always send it through as lsl.
2504 // ('as' compatibility)
2505 if (Imm == 0)
2506 ShiftTy = ARM_AM::lsl;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002507 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002508 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002509 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002510 if (ShiftReg == -1) {
2511 Error (L, "expected immediate or register in shift operand");
2512 return -1;
2513 }
2514 } else {
2515 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002516 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002517 return -1;
2518 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002519 }
2520
Owen Andersonb595ed02011-07-21 18:54:16 +00002521 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2522 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002523 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002524 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002525 else
2526 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2527 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002528
Jim Grosbachbb24c592011-07-13 18:49:30 +00002529 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002530}
2531
2532
Bill Wendling2063b842010-11-18 23:43:05 +00002533/// Try to parse a register name. The token must be an Identifier when called.
2534/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2535/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002536///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002537/// TODO this is likely to change to allow different register types and or to
2538/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002539bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002540tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002541 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002542 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002543 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002544 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002545
Bill Wendling2063b842010-11-18 23:43:05 +00002546 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002547
Chris Lattner44e5981c2010-10-30 04:09:10 +00002548 const AsmToken &ExclaimTok = Parser.getTok();
2549 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002550 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2551 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002552 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002553 return false;
2554 }
2555
2556 // Also check for an index operand. This is only legal for vector registers,
2557 // but that'll get caught OK in operand matching, so we don't need to
2558 // explicitly filter everything else out here.
2559 if (Parser.getTok().is(AsmToken::LBrac)) {
2560 SMLoc SIdx = Parser.getTok().getLoc();
2561 Parser.Lex(); // Eat left bracket token.
2562
2563 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002564 if (getParser().ParseExpression(ImmVal))
Jim Grosbacha2147ce2012-01-31 23:51:09 +00002565 return true;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002566 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachc8f2b782012-01-26 15:56:45 +00002567 if (!MCE)
2568 return TokError("immediate value expected for vector index");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002569
2570 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachc8f2b782012-01-26 15:56:45 +00002571 if (Parser.getTok().isNot(AsmToken::RBrac))
2572 return Error(E, "']' expected");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002573
2574 Parser.Lex(); // Eat right bracket token.
2575
2576 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2577 SIdx, E,
2578 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002579 }
2580
Bill Wendling2063b842010-11-18 23:43:05 +00002581 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002582}
2583
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002584/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2585/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2586/// "c5", ...
2587static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002588 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2589 // but efficient.
2590 switch (Name.size()) {
David Blaikie46a9f012012-01-20 21:51:11 +00002591 default: return -1;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002592 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002593 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002594 return -1;
2595 switch (Name[1]) {
2596 default: return -1;
2597 case '0': return 0;
2598 case '1': return 1;
2599 case '2': return 2;
2600 case '3': return 3;
2601 case '4': return 4;
2602 case '5': return 5;
2603 case '6': return 6;
2604 case '7': return 7;
2605 case '8': return 8;
2606 case '9': return 9;
2607 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002608 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002609 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002610 return -1;
2611 switch (Name[2]) {
2612 default: return -1;
2613 case '0': return 10;
2614 case '1': return 11;
2615 case '2': return 12;
2616 case '3': return 13;
2617 case '4': return 14;
2618 case '5': return 15;
2619 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002620 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002621}
2622
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002623/// parseITCondCode - Try to parse a condition code for an IT instruction.
2624ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2625parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2626 SMLoc S = Parser.getTok().getLoc();
2627 const AsmToken &Tok = Parser.getTok();
2628 if (!Tok.is(AsmToken::Identifier))
2629 return MatchOperand_NoMatch;
2630 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2631 .Case("eq", ARMCC::EQ)
2632 .Case("ne", ARMCC::NE)
2633 .Case("hs", ARMCC::HS)
2634 .Case("cs", ARMCC::HS)
2635 .Case("lo", ARMCC::LO)
2636 .Case("cc", ARMCC::LO)
2637 .Case("mi", ARMCC::MI)
2638 .Case("pl", ARMCC::PL)
2639 .Case("vs", ARMCC::VS)
2640 .Case("vc", ARMCC::VC)
2641 .Case("hi", ARMCC::HI)
2642 .Case("ls", ARMCC::LS)
2643 .Case("ge", ARMCC::GE)
2644 .Case("lt", ARMCC::LT)
2645 .Case("gt", ARMCC::GT)
2646 .Case("le", ARMCC::LE)
2647 .Case("al", ARMCC::AL)
2648 .Default(~0U);
2649 if (CC == ~0U)
2650 return MatchOperand_NoMatch;
2651 Parser.Lex(); // Eat the token.
2652
2653 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2654
2655 return MatchOperand_Success;
2656}
2657
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002658/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002659/// token must be an Identifier when called, and if it is a coprocessor
2660/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002661ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002662parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002663 SMLoc S = Parser.getTok().getLoc();
2664 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002665 if (Tok.isNot(AsmToken::Identifier))
2666 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002667
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002668 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002669 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002670 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002671
2672 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002673 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002674 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002675}
2676
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002677/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002678/// token must be an Identifier when called, and if it is a coprocessor
2679/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002680ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002681parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002682 SMLoc S = Parser.getTok().getLoc();
2683 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002684 if (Tok.isNot(AsmToken::Identifier))
2685 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002686
2687 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2688 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002689 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002690
2691 Parser.Lex(); // Eat identifier token.
2692 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002693 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002694}
2695
Jim Grosbach48399582011-10-12 17:34:41 +00002696/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2697/// coproc_option : '{' imm0_255 '}'
2698ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2699parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2700 SMLoc S = Parser.getTok().getLoc();
2701
2702 // If this isn't a '{', this isn't a coprocessor immediate operand.
2703 if (Parser.getTok().isNot(AsmToken::LCurly))
2704 return MatchOperand_NoMatch;
2705 Parser.Lex(); // Eat the '{'
2706
2707 const MCExpr *Expr;
2708 SMLoc Loc = Parser.getTok().getLoc();
2709 if (getParser().ParseExpression(Expr)) {
2710 Error(Loc, "illegal expression");
2711 return MatchOperand_ParseFail;
2712 }
2713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2714 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2715 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2716 return MatchOperand_ParseFail;
2717 }
2718 int Val = CE->getValue();
2719
2720 // Check for and consume the closing '}'
2721 if (Parser.getTok().isNot(AsmToken::RCurly))
2722 return MatchOperand_ParseFail;
2723 SMLoc E = Parser.getTok().getLoc();
2724 Parser.Lex(); // Eat the '}'
2725
2726 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2727 return MatchOperand_Success;
2728}
2729
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002730// For register list parsing, we need to map from raw GPR register numbering
2731// to the enumeration values. The enumeration values aren't sorted by
2732// register number due to our using "sp", "lr" and "pc" as canonical names.
2733static unsigned getNextRegister(unsigned Reg) {
2734 // If this is a GPR, we need to do it manually, otherwise we can rely
2735 // on the sort ordering of the enumeration since the other reg-classes
2736 // are sane.
2737 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2738 return Reg + 1;
2739 switch(Reg) {
Craig Toppere55c5562012-02-07 02:50:20 +00002740 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002741 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2742 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2743 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2744 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2745 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2746 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2747 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2748 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2749 }
2750}
2751
Jim Grosbach85a23432011-11-11 21:27:40 +00002752// Return the low-subreg of a given Q register.
2753static unsigned getDRegFromQReg(unsigned QReg) {
2754 switch (QReg) {
2755 default: llvm_unreachable("expected a Q register!");
2756 case ARM::Q0: return ARM::D0;
2757 case ARM::Q1: return ARM::D2;
2758 case ARM::Q2: return ARM::D4;
2759 case ARM::Q3: return ARM::D6;
2760 case ARM::Q4: return ARM::D8;
2761 case ARM::Q5: return ARM::D10;
2762 case ARM::Q6: return ARM::D12;
2763 case ARM::Q7: return ARM::D14;
2764 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002765 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002766 case ARM::Q10: return ARM::D20;
2767 case ARM::Q11: return ARM::D22;
2768 case ARM::Q12: return ARM::D24;
2769 case ARM::Q13: return ARM::D26;
2770 case ARM::Q14: return ARM::D28;
2771 case ARM::Q15: return ARM::D30;
2772 }
2773}
2774
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002775/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002776bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002777parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002778 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002779 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002780 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002781 Parser.Lex(); // Eat '{' token.
2782 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002783
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002784 // Check the first register in the list to see what register class
2785 // this is a list of.
2786 int Reg = tryParseRegister();
2787 if (Reg == -1)
2788 return Error(RegLoc, "register expected");
2789
Jim Grosbach85a23432011-11-11 21:27:40 +00002790 // The reglist instructions have at most 16 registers, so reserve
2791 // space for that many.
2792 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2793
2794 // Allow Q regs and just interpret them as the two D sub-registers.
2795 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2796 Reg = getDRegFromQReg(Reg);
2797 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2798 ++Reg;
2799 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002800 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002801 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2802 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2803 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2804 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2805 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2806 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2807 else
2808 return Error(RegLoc, "invalid register in register list");
2809
Jim Grosbach85a23432011-11-11 21:27:40 +00002810 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002811 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002812
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002813 // This starts immediately after the first register token in the list,
2814 // so we can see either a comma or a minus (range separator) as a legal
2815 // next token.
2816 while (Parser.getTok().is(AsmToken::Comma) ||
2817 Parser.getTok().is(AsmToken::Minus)) {
2818 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002819 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002820 SMLoc EndLoc = Parser.getTok().getLoc();
2821 int EndReg = tryParseRegister();
2822 if (EndReg == -1)
2823 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002824 // Allow Q regs and just interpret them as the two D sub-registers.
2825 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2826 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002827 // If the register is the same as the start reg, there's nothing
2828 // more to do.
2829 if (Reg == EndReg)
2830 continue;
2831 // The register must be in the same register class as the first.
2832 if (!RC->contains(EndReg))
2833 return Error(EndLoc, "invalid register in register list");
2834 // Ranges must go from low to high.
2835 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2836 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002837
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002838 // Add all the registers in the range to the register list.
2839 while (Reg != EndReg) {
2840 Reg = getNextRegister(Reg);
2841 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2842 }
2843 continue;
2844 }
2845 Parser.Lex(); // Eat the comma.
2846 RegLoc = Parser.getTok().getLoc();
2847 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002848 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002849 Reg = tryParseRegister();
2850 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002851 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002852 // Allow Q regs and just interpret them as the two D sub-registers.
2853 bool isQReg = false;
2854 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2855 Reg = getDRegFromQReg(Reg);
2856 isQReg = true;
2857 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002858 // The register must be in the same register class as the first.
2859 if (!RC->contains(Reg))
2860 return Error(RegLoc, "invalid register in register list");
2861 // List must be monotonically increasing.
Jim Grosbach98bc7972011-12-08 21:34:20 +00002862 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002863 return Error(RegLoc, "register list not in ascending order");
Jim Grosbach98bc7972011-12-08 21:34:20 +00002864 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2865 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2866 ") in register list");
2867 continue;
2868 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002869 // VFP register lists must also be contiguous.
2870 // It's OK to use the enumeration values directly here rather, as the
2871 // VFP register classes have the enum sorted properly.
2872 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2873 Reg != OldReg + 1)
2874 return Error(RegLoc, "non-contiguous register range");
2875 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002876 if (isQReg)
2877 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002878 }
2879
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002880 SMLoc E = Parser.getTok().getLoc();
2881 if (Parser.getTok().isNot(AsmToken::RCurly))
2882 return Error(E, "'}' expected");
2883 Parser.Lex(); // Eat '}' token.
2884
Jim Grosbach18bf3632011-12-13 21:48:29 +00002885 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002886 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002887
2888 // The ARM system instruction variants for LDM/STM have a '^' token here.
2889 if (Parser.getTok().is(AsmToken::Caret)) {
2890 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2891 Parser.Lex(); // Eat '^' token.
2892 }
2893
Bill Wendling2063b842010-11-18 23:43:05 +00002894 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002895}
2896
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002897// Helper function to parse the lane index for vector lists.
2898ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002899parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2900 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002901 if (Parser.getTok().is(AsmToken::LBrac)) {
2902 Parser.Lex(); // Eat the '['.
2903 if (Parser.getTok().is(AsmToken::RBrac)) {
2904 // "Dn[]" is the 'all lanes' syntax.
2905 LaneKind = AllLanes;
2906 Parser.Lex(); // Eat the ']'.
2907 return MatchOperand_Success;
2908 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002909 const MCExpr *LaneIndex;
2910 SMLoc Loc = Parser.getTok().getLoc();
2911 if (getParser().ParseExpression(LaneIndex)) {
2912 Error(Loc, "illegal expression");
2913 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002914 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002915 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2916 if (!CE) {
2917 Error(Loc, "lane index must be empty or an integer");
2918 return MatchOperand_ParseFail;
2919 }
2920 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2921 Error(Parser.getTok().getLoc(), "']' expected");
2922 return MatchOperand_ParseFail;
2923 }
2924 Parser.Lex(); // Eat the ']'.
2925 int64_t Val = CE->getValue();
2926
2927 // FIXME: Make this range check context sensitive for .8, .16, .32.
2928 if (Val < 0 || Val > 7) {
2929 Error(Parser.getTok().getLoc(), "lane index out of range");
2930 return MatchOperand_ParseFail;
2931 }
2932 Index = Val;
2933 LaneKind = IndexedLane;
2934 return MatchOperand_Success;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002935 }
2936 LaneKind = NoLanes;
2937 return MatchOperand_Success;
2938}
2939
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002940// parse a vector register list
2941ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2942parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002943 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002944 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002945 SMLoc S = Parser.getTok().getLoc();
2946 // As an extension (to match gas), support a plain D register or Q register
2947 // (without encosing curly braces) as a single or double entry list,
2948 // respectively.
2949 if (Parser.getTok().is(AsmToken::Identifier)) {
2950 int Reg = tryParseRegister();
2951 if (Reg == -1)
2952 return MatchOperand_NoMatch;
2953 SMLoc E = Parser.getTok().getLoc();
2954 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002955 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002956 if (Res != MatchOperand_Success)
2957 return Res;
2958 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002959 case NoLanes:
2960 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002961 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002962 break;
2963 case AllLanes:
2964 E = Parser.getTok().getLoc();
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002965 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2966 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002967 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002968 case IndexedLane:
2969 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002970 LaneIndex,
2971 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002972 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002973 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002974 return MatchOperand_Success;
2975 }
2976 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2977 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002978 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002979 if (Res != MatchOperand_Success)
2980 return Res;
2981 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002982 case NoLanes:
2983 E = Parser.getTok().getLoc();
Jim Grosbachc988e0c2012-03-05 19:33:30 +00002984 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbach13a292c2012-03-06 22:01:44 +00002985 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach2f50e922011-12-15 21:44:33 +00002986 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002987 break;
2988 case AllLanes:
2989 E = Parser.getTok().getLoc();
Jim Grosbach13a292c2012-03-06 22:01:44 +00002990 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
2991 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002992 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2993 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002994 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002995 case IndexedLane:
2996 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002997 LaneIndex,
2998 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002999 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003000 }
Jim Grosbach8d579232011-11-15 21:45:55 +00003001 return MatchOperand_Success;
3002 }
3003 Error(S, "vector register expected");
3004 return MatchOperand_ParseFail;
3005 }
3006
3007 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003008 return MatchOperand_NoMatch;
3009
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003010 Parser.Lex(); // Eat '{' token.
3011 SMLoc RegLoc = Parser.getTok().getLoc();
3012
3013 int Reg = tryParseRegister();
3014 if (Reg == -1) {
3015 Error(RegLoc, "register expected");
3016 return MatchOperand_ParseFail;
3017 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003018 unsigned Count = 1;
Jim Grosbachc2f16a32011-12-15 21:54:55 +00003019 int Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00003020 unsigned FirstReg = Reg;
3021 // The list is of D registers, but we also allow Q regs and just interpret
3022 // them as the two D sub-registers.
3023 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3024 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00003025 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3026 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00003027 ++Reg;
3028 ++Count;
3029 }
Jim Grosbach04945c42011-12-02 00:35:16 +00003030 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003031 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00003032
Jim Grosbache891fe82011-11-15 23:19:15 +00003033 while (Parser.getTok().is(AsmToken::Comma) ||
3034 Parser.getTok().is(AsmToken::Minus)) {
3035 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003036 if (!Spacing)
3037 Spacing = 1; // Register range implies a single spaced list.
3038 else if (Spacing == 2) {
3039 Error(Parser.getTok().getLoc(),
3040 "sequential registers in double spaced list");
3041 return MatchOperand_ParseFail;
3042 }
Jim Grosbache891fe82011-11-15 23:19:15 +00003043 Parser.Lex(); // Eat the minus.
3044 SMLoc EndLoc = Parser.getTok().getLoc();
3045 int EndReg = tryParseRegister();
3046 if (EndReg == -1) {
3047 Error(EndLoc, "register expected");
3048 return MatchOperand_ParseFail;
3049 }
3050 // Allow Q regs and just interpret them as the two D sub-registers.
3051 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3052 EndReg = getDRegFromQReg(EndReg) + 1;
3053 // If the register is the same as the start reg, there's nothing
3054 // more to do.
3055 if (Reg == EndReg)
3056 continue;
3057 // The register must be in the same register class as the first.
3058 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3059 Error(EndLoc, "invalid register in register list");
3060 return MatchOperand_ParseFail;
3061 }
3062 // Ranges must go from low to high.
3063 if (Reg > EndReg) {
3064 Error(EndLoc, "bad range in register list");
3065 return MatchOperand_ParseFail;
3066 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003067 // Parse the lane specifier if present.
3068 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003069 unsigned NextLaneIndex;
3070 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003071 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003072 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003073 Error(EndLoc, "mismatched lane index in register list");
3074 return MatchOperand_ParseFail;
3075 }
3076 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00003077
3078 // Add all the registers in the range to the register list.
3079 Count += EndReg - Reg;
3080 Reg = EndReg;
3081 continue;
3082 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003083 Parser.Lex(); // Eat the comma.
3084 RegLoc = Parser.getTok().getLoc();
3085 int OldReg = Reg;
3086 Reg = tryParseRegister();
3087 if (Reg == -1) {
3088 Error(RegLoc, "register expected");
3089 return MatchOperand_ParseFail;
3090 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003091 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003092 // It's OK to use the enumeration values directly here rather, as the
3093 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00003094 //
3095 // The list is of D registers, but we also allow Q regs and just interpret
3096 // them as the two D sub-registers.
3097 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003098 if (!Spacing)
3099 Spacing = 1; // Register range implies a single spaced list.
3100 else if (Spacing == 2) {
3101 Error(RegLoc,
3102 "invalid register in double-spaced list (must be 'D' register')");
3103 return MatchOperand_ParseFail;
3104 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003105 Reg = getDRegFromQReg(Reg);
3106 if (Reg != OldReg + 1) {
3107 Error(RegLoc, "non-contiguous register range");
3108 return MatchOperand_ParseFail;
3109 }
3110 ++Reg;
3111 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003112 // Parse the lane specifier if present.
3113 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003114 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003115 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003116 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003117 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003118 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003119 Error(EndLoc, "mismatched lane index in register list");
3120 return MatchOperand_ParseFail;
3121 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003122 continue;
3123 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00003124 // Normal D register.
3125 // Figure out the register spacing (single or double) of the list if
3126 // we don't know it already.
3127 if (!Spacing)
3128 Spacing = 1 + (Reg == OldReg + 2);
3129
3130 // Just check that it's contiguous and keep going.
3131 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003132 Error(RegLoc, "non-contiguous register range");
3133 return MatchOperand_ParseFail;
3134 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003135 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003136 // Parse the lane specifier if present.
3137 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003138 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003139 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003140 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003141 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003142 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003143 Error(EndLoc, "mismatched lane index in register list");
3144 return MatchOperand_ParseFail;
3145 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003146 }
3147
3148 SMLoc E = Parser.getTok().getLoc();
3149 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3150 Error(E, "'}' expected");
3151 return MatchOperand_ParseFail;
3152 }
3153 Parser.Lex(); // Eat '}' token.
3154
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003155 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003156 case NoLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003157 // Two-register operands have been converted to the
Jim Grosbache5307f92012-03-05 21:43:40 +00003158 // composite register classes.
3159 if (Count == 2) {
3160 const MCRegisterClass *RC = (Spacing == 1) ?
3161 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3162 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3163 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3164 }
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003165
Jim Grosbach2f50e922011-12-15 21:44:33 +00003166 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3167 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003168 break;
3169 case AllLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003170 // Two-register operands have been converted to the
3171 // composite register classes.
3172 if (Count == 2 && Spacing == 1) {
3173 const MCRegisterClass *RC = &ARMMCRegisterClasses[ARM::DPairRegClassID];
3174 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3175 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003176 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003177 (Spacing == 2),
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003178 S, E));
3179 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003180 case IndexedLane:
3181 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003182 LaneIndex,
3183 (Spacing == 2),
3184 S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003185 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003186 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003187 return MatchOperand_Success;
3188}
3189
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003190/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003191ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003192parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003193 SMLoc S = Parser.getTok().getLoc();
3194 const AsmToken &Tok = Parser.getTok();
3195 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3196 StringRef OptStr = Tok.getString();
3197
3198 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3199 .Case("sy", ARM_MB::SY)
3200 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003201 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003202 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003203 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003204 .Case("ishst", ARM_MB::ISHST)
3205 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003206 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003207 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003208 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003209 .Case("osh", ARM_MB::OSH)
3210 .Case("oshst", ARM_MB::OSHST)
3211 .Default(~0U);
3212
3213 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003214 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003215
3216 Parser.Lex(); // Eat identifier token.
3217 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003218 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003219}
3220
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003221/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003222ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003223parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003224 SMLoc S = Parser.getTok().getLoc();
3225 const AsmToken &Tok = Parser.getTok();
3226 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3227 StringRef IFlagsStr = Tok.getString();
3228
Owen Anderson10c5b122011-10-05 17:16:40 +00003229 // An iflags string of "none" is interpreted to mean that none of the AIF
3230 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003231 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003232 if (IFlagsStr != "none") {
3233 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3234 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3235 .Case("a", ARM_PROC::A)
3236 .Case("i", ARM_PROC::I)
3237 .Case("f", ARM_PROC::F)
3238 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003239
Owen Anderson10c5b122011-10-05 17:16:40 +00003240 // If some specific iflag is already set, it means that some letter is
3241 // present more than once, this is not acceptable.
3242 if (Flag == ~0U || (IFlags & Flag))
3243 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003244
Owen Anderson10c5b122011-10-05 17:16:40 +00003245 IFlags |= Flag;
3246 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003247 }
3248
3249 Parser.Lex(); // Eat identifier token.
3250 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3251 return MatchOperand_Success;
3252}
3253
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003254/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003255ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003256parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003257 SMLoc S = Parser.getTok().getLoc();
3258 const AsmToken &Tok = Parser.getTok();
3259 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3260 StringRef Mask = Tok.getString();
3261
James Molloy21efa7d2011-09-28 14:21:38 +00003262 if (isMClass()) {
3263 // See ARMv6-M 10.1.1
3264 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3265 .Case("apsr", 0)
3266 .Case("iapsr", 1)
3267 .Case("eapsr", 2)
3268 .Case("xpsr", 3)
3269 .Case("ipsr", 5)
3270 .Case("epsr", 6)
3271 .Case("iepsr", 7)
3272 .Case("msp", 8)
3273 .Case("psp", 9)
3274 .Case("primask", 16)
3275 .Case("basepri", 17)
3276 .Case("basepri_max", 18)
3277 .Case("faultmask", 19)
3278 .Case("control", 20)
3279 .Default(~0U);
Jim Grosbach3794d822011-12-22 17:17:10 +00003280
James Molloy21efa7d2011-09-28 14:21:38 +00003281 if (FlagsVal == ~0U)
3282 return MatchOperand_NoMatch;
3283
3284 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3285 // basepri, basepri_max and faultmask only valid for V7m.
3286 return MatchOperand_NoMatch;
Jim Grosbach3794d822011-12-22 17:17:10 +00003287
James Molloy21efa7d2011-09-28 14:21:38 +00003288 Parser.Lex(); // Eat identifier token.
3289 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3290 return MatchOperand_Success;
3291 }
3292
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003293 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3294 size_t Start = 0, Next = Mask.find('_');
3295 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003296 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003297 if (Next != StringRef::npos)
3298 Flags = Mask.slice(Next+1, Mask.size());
3299
3300 // FlagsVal contains the complete mask:
3301 // 3-0: Mask
3302 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3303 unsigned FlagsVal = 0;
3304
3305 if (SpecReg == "apsr") {
3306 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003307 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003308 .Case("g", 0x4) // same as CPSR_s
3309 .Case("nzcvqg", 0xc) // same as CPSR_fs
3310 .Default(~0U);
3311
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003312 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003313 if (!Flags.empty())
3314 return MatchOperand_NoMatch;
3315 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003316 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003317 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003318 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003319 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3320 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003321 for (int i = 0, e = Flags.size(); i != e; ++i) {
3322 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3323 .Case("c", 1)
3324 .Case("x", 2)
3325 .Case("s", 4)
3326 .Case("f", 8)
3327 .Default(~0U);
3328
3329 // If some specific flag is already set, it means that some letter is
3330 // present more than once, this is not acceptable.
3331 if (FlagsVal == ~0U || (FlagsVal & Flag))
3332 return MatchOperand_NoMatch;
3333 FlagsVal |= Flag;
3334 }
3335 } else // No match for special register.
3336 return MatchOperand_NoMatch;
3337
Owen Anderson03a173e2011-10-21 18:43:28 +00003338 // Special register without flags is NOT equivalent to "fc" flags.
3339 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3340 // two lines would enable gas compatibility at the expense of breaking
3341 // round-tripping.
3342 //
3343 // if (!FlagsVal)
3344 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003345
3346 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3347 if (SpecReg == "spsr")
3348 FlagsVal |= 16;
3349
3350 Parser.Lex(); // Eat identifier token.
3351 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3352 return MatchOperand_Success;
3353}
3354
Jim Grosbach27c1e252011-07-21 17:23:04 +00003355ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3356parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3357 int Low, int High) {
3358 const AsmToken &Tok = Parser.getTok();
3359 if (Tok.isNot(AsmToken::Identifier)) {
3360 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3361 return MatchOperand_ParseFail;
3362 }
3363 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003364 std::string LowerOp = Op.lower();
3365 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003366 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3367 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3368 return MatchOperand_ParseFail;
3369 }
3370 Parser.Lex(); // Eat shift type token.
3371
3372 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003373 if (Parser.getTok().isNot(AsmToken::Hash) &&
3374 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003375 Error(Parser.getTok().getLoc(), "'#' expected");
3376 return MatchOperand_ParseFail;
3377 }
3378 Parser.Lex(); // Eat hash token.
3379
3380 const MCExpr *ShiftAmount;
3381 SMLoc Loc = Parser.getTok().getLoc();
3382 if (getParser().ParseExpression(ShiftAmount)) {
3383 Error(Loc, "illegal expression");
3384 return MatchOperand_ParseFail;
3385 }
3386 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3387 if (!CE) {
3388 Error(Loc, "constant expression expected");
3389 return MatchOperand_ParseFail;
3390 }
3391 int Val = CE->getValue();
3392 if (Val < Low || Val > High) {
3393 Error(Loc, "immediate value out of range");
3394 return MatchOperand_ParseFail;
3395 }
3396
3397 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3398
3399 return MatchOperand_Success;
3400}
3401
Jim Grosbach0a547702011-07-22 17:44:50 +00003402ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3403parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3404 const AsmToken &Tok = Parser.getTok();
3405 SMLoc S = Tok.getLoc();
3406 if (Tok.isNot(AsmToken::Identifier)) {
3407 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3408 return MatchOperand_ParseFail;
3409 }
3410 int Val = StringSwitch<int>(Tok.getString())
3411 .Case("be", 1)
3412 .Case("le", 0)
3413 .Default(-1);
3414 Parser.Lex(); // Eat the token.
3415
3416 if (Val == -1) {
3417 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3418 return MatchOperand_ParseFail;
3419 }
3420 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3421 getContext()),
3422 S, Parser.getTok().getLoc()));
3423 return MatchOperand_Success;
3424}
3425
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003426/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3427/// instructions. Legal values are:
3428/// lsl #n 'n' in [0,31]
3429/// asr #n 'n' in [1,32]
3430/// n == 32 encoded as n == 0.
3431ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3432parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3433 const AsmToken &Tok = Parser.getTok();
3434 SMLoc S = Tok.getLoc();
3435 if (Tok.isNot(AsmToken::Identifier)) {
3436 Error(S, "shift operator 'asr' or 'lsl' expected");
3437 return MatchOperand_ParseFail;
3438 }
3439 StringRef ShiftName = Tok.getString();
3440 bool isASR;
3441 if (ShiftName == "lsl" || ShiftName == "LSL")
3442 isASR = false;
3443 else if (ShiftName == "asr" || ShiftName == "ASR")
3444 isASR = true;
3445 else {
3446 Error(S, "shift operator 'asr' or 'lsl' expected");
3447 return MatchOperand_ParseFail;
3448 }
3449 Parser.Lex(); // Eat the operator.
3450
3451 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003452 if (Parser.getTok().isNot(AsmToken::Hash) &&
3453 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003454 Error(Parser.getTok().getLoc(), "'#' expected");
3455 return MatchOperand_ParseFail;
3456 }
3457 Parser.Lex(); // Eat hash token.
3458
3459 const MCExpr *ShiftAmount;
3460 SMLoc E = Parser.getTok().getLoc();
3461 if (getParser().ParseExpression(ShiftAmount)) {
3462 Error(E, "malformed shift expression");
3463 return MatchOperand_ParseFail;
3464 }
3465 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3466 if (!CE) {
3467 Error(E, "shift amount must be an immediate");
3468 return MatchOperand_ParseFail;
3469 }
3470
3471 int64_t Val = CE->getValue();
3472 if (isASR) {
3473 // Shift amount must be in [1,32]
3474 if (Val < 1 || Val > 32) {
3475 Error(E, "'asr' shift amount must be in range [1,32]");
3476 return MatchOperand_ParseFail;
3477 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003478 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3479 if (isThumb() && Val == 32) {
3480 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3481 return MatchOperand_ParseFail;
3482 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003483 if (Val == 32) Val = 0;
3484 } else {
3485 // Shift amount must be in [1,32]
3486 if (Val < 0 || Val > 31) {
3487 Error(E, "'lsr' shift amount must be in range [0,31]");
3488 return MatchOperand_ParseFail;
3489 }
3490 }
3491
3492 E = Parser.getTok().getLoc();
3493 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3494
3495 return MatchOperand_Success;
3496}
3497
Jim Grosbach833b9d32011-07-27 20:15:40 +00003498/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3499/// of instructions. Legal values are:
3500/// ror #n 'n' in {0, 8, 16, 24}
3501ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3502parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3503 const AsmToken &Tok = Parser.getTok();
3504 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003505 if (Tok.isNot(AsmToken::Identifier))
3506 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003507 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003508 if (ShiftName != "ror" && ShiftName != "ROR")
3509 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003510 Parser.Lex(); // Eat the operator.
3511
3512 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003513 if (Parser.getTok().isNot(AsmToken::Hash) &&
3514 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003515 Error(Parser.getTok().getLoc(), "'#' expected");
3516 return MatchOperand_ParseFail;
3517 }
3518 Parser.Lex(); // Eat hash token.
3519
3520 const MCExpr *ShiftAmount;
3521 SMLoc E = Parser.getTok().getLoc();
3522 if (getParser().ParseExpression(ShiftAmount)) {
3523 Error(E, "malformed rotate expression");
3524 return MatchOperand_ParseFail;
3525 }
3526 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3527 if (!CE) {
3528 Error(E, "rotate amount must be an immediate");
3529 return MatchOperand_ParseFail;
3530 }
3531
3532 int64_t Val = CE->getValue();
3533 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3534 // normally, zero is represented in asm by omitting the rotate operand
3535 // entirely.
3536 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3537 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3538 return MatchOperand_ParseFail;
3539 }
3540
3541 E = Parser.getTok().getLoc();
3542 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3543
3544 return MatchOperand_Success;
3545}
3546
Jim Grosbach864b6092011-07-28 21:34:26 +00003547ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3548parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3549 SMLoc S = Parser.getTok().getLoc();
3550 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003551 if (Parser.getTok().isNot(AsmToken::Hash) &&
3552 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003553 Error(Parser.getTok().getLoc(), "'#' expected");
3554 return MatchOperand_ParseFail;
3555 }
3556 Parser.Lex(); // Eat hash token.
3557
3558 const MCExpr *LSBExpr;
3559 SMLoc E = Parser.getTok().getLoc();
3560 if (getParser().ParseExpression(LSBExpr)) {
3561 Error(E, "malformed immediate expression");
3562 return MatchOperand_ParseFail;
3563 }
3564 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3565 if (!CE) {
3566 Error(E, "'lsb' operand must be an immediate");
3567 return MatchOperand_ParseFail;
3568 }
3569
3570 int64_t LSB = CE->getValue();
3571 // The LSB must be in the range [0,31]
3572 if (LSB < 0 || LSB > 31) {
3573 Error(E, "'lsb' operand must be in the range [0,31]");
3574 return MatchOperand_ParseFail;
3575 }
3576 E = Parser.getTok().getLoc();
3577
3578 // Expect another immediate operand.
3579 if (Parser.getTok().isNot(AsmToken::Comma)) {
3580 Error(Parser.getTok().getLoc(), "too few operands");
3581 return MatchOperand_ParseFail;
3582 }
3583 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003584 if (Parser.getTok().isNot(AsmToken::Hash) &&
3585 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003586 Error(Parser.getTok().getLoc(), "'#' expected");
3587 return MatchOperand_ParseFail;
3588 }
3589 Parser.Lex(); // Eat hash token.
3590
3591 const MCExpr *WidthExpr;
3592 if (getParser().ParseExpression(WidthExpr)) {
3593 Error(E, "malformed immediate expression");
3594 return MatchOperand_ParseFail;
3595 }
3596 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3597 if (!CE) {
3598 Error(E, "'width' operand must be an immediate");
3599 return MatchOperand_ParseFail;
3600 }
3601
3602 int64_t Width = CE->getValue();
3603 // The LSB must be in the range [1,32-lsb]
3604 if (Width < 1 || Width > 32 - LSB) {
3605 Error(E, "'width' operand must be in the range [1,32-lsb]");
3606 return MatchOperand_ParseFail;
3607 }
3608 E = Parser.getTok().getLoc();
3609
3610 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3611
3612 return MatchOperand_Success;
3613}
3614
Jim Grosbachd3595712011-08-03 23:50:40 +00003615ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3616parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3617 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003618 // postidx_reg := '+' register {, shift}
3619 // | '-' register {, shift}
3620 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003621
3622 // This method must return MatchOperand_NoMatch without consuming any tokens
3623 // in the case where there is no match, as other alternatives take other
3624 // parse methods.
3625 AsmToken Tok = Parser.getTok();
3626 SMLoc S = Tok.getLoc();
3627 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003628 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003629 int Reg = -1;
3630 if (Tok.is(AsmToken::Plus)) {
3631 Parser.Lex(); // Eat the '+' token.
3632 haveEaten = true;
3633 } else if (Tok.is(AsmToken::Minus)) {
3634 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003635 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003636 haveEaten = true;
3637 }
3638 if (Parser.getTok().is(AsmToken::Identifier))
3639 Reg = tryParseRegister();
3640 if (Reg == -1) {
3641 if (!haveEaten)
3642 return MatchOperand_NoMatch;
3643 Error(Parser.getTok().getLoc(), "register expected");
3644 return MatchOperand_ParseFail;
3645 }
3646 SMLoc E = Parser.getTok().getLoc();
3647
Jim Grosbachc320c852011-08-05 21:28:30 +00003648 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3649 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003650 if (Parser.getTok().is(AsmToken::Comma)) {
3651 Parser.Lex(); // Eat the ','.
3652 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3653 return MatchOperand_ParseFail;
3654 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003655
3656 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3657 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003658
3659 return MatchOperand_Success;
3660}
3661
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003662ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3663parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3664 // Check for a post-index addressing register operand. Specifically:
3665 // am3offset := '+' register
3666 // | '-' register
3667 // | register
3668 // | # imm
3669 // | # + imm
3670 // | # - imm
3671
3672 // This method must return MatchOperand_NoMatch without consuming any tokens
3673 // in the case where there is no match, as other alternatives take other
3674 // parse methods.
3675 AsmToken Tok = Parser.getTok();
3676 SMLoc S = Tok.getLoc();
3677
3678 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003679 if (Parser.getTok().is(AsmToken::Hash) ||
3680 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003681 Parser.Lex(); // Eat the '#'.
3682 // Explicitly look for a '-', as we need to encode negative zero
3683 // differently.
3684 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3685 const MCExpr *Offset;
3686 if (getParser().ParseExpression(Offset))
3687 return MatchOperand_ParseFail;
3688 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3689 if (!CE) {
3690 Error(S, "constant expression expected");
3691 return MatchOperand_ParseFail;
3692 }
3693 SMLoc E = Tok.getLoc();
3694 // Negative zero is encoded as the flag value INT32_MIN.
3695 int32_t Val = CE->getValue();
3696 if (isNegative && Val == 0)
3697 Val = INT32_MIN;
3698
3699 Operands.push_back(
3700 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3701
3702 return MatchOperand_Success;
3703 }
3704
3705
3706 bool haveEaten = false;
3707 bool isAdd = true;
3708 int Reg = -1;
3709 if (Tok.is(AsmToken::Plus)) {
3710 Parser.Lex(); // Eat the '+' token.
3711 haveEaten = true;
3712 } else if (Tok.is(AsmToken::Minus)) {
3713 Parser.Lex(); // Eat the '-' token.
3714 isAdd = false;
3715 haveEaten = true;
3716 }
3717 if (Parser.getTok().is(AsmToken::Identifier))
3718 Reg = tryParseRegister();
3719 if (Reg == -1) {
3720 if (!haveEaten)
3721 return MatchOperand_NoMatch;
3722 Error(Parser.getTok().getLoc(), "register expected");
3723 return MatchOperand_ParseFail;
3724 }
3725 SMLoc E = Parser.getTok().getLoc();
3726
3727 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3728 0, S, E));
3729
3730 return MatchOperand_Success;
3731}
3732
Jim Grosbach7db8d692011-09-08 22:07:06 +00003733/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3734/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3735/// when they refer multiple MIOperands inside a single one.
3736bool ARMAsmParser::
3737cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3738 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3739 // Rt, Rt2
3740 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3741 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3742 // Create a writeback register dummy placeholder.
3743 Inst.addOperand(MCOperand::CreateReg(0));
3744 // addr
3745 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3746 // pred
3747 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3748 return true;
3749}
3750
3751/// cvtT2StrdPre - Convert parsed operands to MCInst.
3752/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3753/// when they refer multiple MIOperands inside a single one.
3754bool ARMAsmParser::
3755cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3756 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3757 // Create a writeback register dummy placeholder.
3758 Inst.addOperand(MCOperand::CreateReg(0));
3759 // Rt, Rt2
3760 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3761 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3762 // addr
3763 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3764 // pred
3765 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3766 return true;
3767}
3768
Jim Grosbachc086f682011-09-08 00:39:19 +00003769/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3770/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3771/// when they refer multiple MIOperands inside a single one.
3772bool ARMAsmParser::
3773cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3774 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3775 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3776
3777 // Create a writeback register dummy placeholder.
3778 Inst.addOperand(MCOperand::CreateImm(0));
3779
3780 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3781 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3782 return true;
3783}
3784
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003785/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3786/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3787/// when they refer multiple MIOperands inside a single one.
3788bool ARMAsmParser::
3789cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3790 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3791 // Create a writeback register dummy placeholder.
3792 Inst.addOperand(MCOperand::CreateImm(0));
3793 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3794 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3795 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3796 return true;
3797}
3798
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003799/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003800/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3801/// when they refer multiple MIOperands inside a single one.
3802bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003803cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003804 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3805 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3806
3807 // Create a writeback register dummy placeholder.
3808 Inst.addOperand(MCOperand::CreateImm(0));
3809
Jim Grosbachd3595712011-08-03 23:50:40 +00003810 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003811 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3812 return true;
3813}
3814
Owen Anderson16d33f32011-08-26 20:43:14 +00003815/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3816/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3817/// when they refer multiple MIOperands inside a single one.
3818bool ARMAsmParser::
3819cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3820 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3821 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3822
3823 // Create a writeback register dummy placeholder.
3824 Inst.addOperand(MCOperand::CreateImm(0));
3825
3826 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3827 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3828 return true;
3829}
3830
3831
Jim Grosbachd564bf32011-08-11 19:22:40 +00003832/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3833/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3834/// when they refer multiple MIOperands inside a single one.
3835bool ARMAsmParser::
3836cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3837 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3838 // Create a writeback register dummy placeholder.
3839 Inst.addOperand(MCOperand::CreateImm(0));
3840 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3841 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3842 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3843 return true;
3844}
3845
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003846/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003847/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3848/// when they refer multiple MIOperands inside a single one.
3849bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003850cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003851 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3852 // Create a writeback register dummy placeholder.
3853 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003854 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3855 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3856 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003857 return true;
3858}
3859
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003860/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3861/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3862/// when they refer multiple MIOperands inside a single one.
3863bool ARMAsmParser::
3864cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3865 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3866 // Create a writeback register dummy placeholder.
3867 Inst.addOperand(MCOperand::CreateImm(0));
3868 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3869 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3870 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3871 return true;
3872}
3873
Jim Grosbachd3595712011-08-03 23:50:40 +00003874/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3875/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3876/// when they refer multiple MIOperands inside a single one.
3877bool ARMAsmParser::
3878cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3879 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3880 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003881 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003882 // Create a writeback register dummy placeholder.
3883 Inst.addOperand(MCOperand::CreateImm(0));
3884 // addr
3885 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3886 // offset
3887 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3888 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003889 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3890 return true;
3891}
3892
Jim Grosbachd3595712011-08-03 23:50:40 +00003893/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003894/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3895/// when they refer multiple MIOperands inside a single one.
3896bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003897cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3898 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3899 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003900 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003901 // Create a writeback register dummy placeholder.
3902 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003903 // addr
3904 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3905 // offset
3906 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3907 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003908 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3909 return true;
3910}
3911
Jim Grosbachd3595712011-08-03 23:50:40 +00003912/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003913/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3914/// when they refer multiple MIOperands inside a single one.
3915bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003916cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3917 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003918 // Create a writeback register dummy placeholder.
3919 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003920 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003921 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003922 // addr
3923 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3924 // offset
3925 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3926 // pred
3927 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3928 return true;
3929}
3930
3931/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3932/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3933/// when they refer multiple MIOperands inside a single one.
3934bool ARMAsmParser::
3935cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3936 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3937 // Create a writeback register dummy placeholder.
3938 Inst.addOperand(MCOperand::CreateImm(0));
3939 // Rt
3940 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3941 // addr
3942 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3943 // offset
3944 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3945 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003946 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3947 return true;
3948}
3949
Jim Grosbach5b96b802011-08-10 20:29:19 +00003950/// cvtLdrdPre - Convert parsed operands to MCInst.
3951/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3952/// when they refer multiple MIOperands inside a single one.
3953bool ARMAsmParser::
3954cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3955 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3956 // Rt, Rt2
3957 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3958 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3959 // Create a writeback register dummy placeholder.
3960 Inst.addOperand(MCOperand::CreateImm(0));
3961 // addr
3962 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3963 // pred
3964 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3965 return true;
3966}
3967
Jim Grosbacheb09f492011-08-11 20:28:23 +00003968/// cvtStrdPre - Convert parsed operands to MCInst.
3969/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3970/// when they refer multiple MIOperands inside a single one.
3971bool ARMAsmParser::
3972cvtStrdPre(MCInst &Inst, unsigned Opcode,
3973 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3974 // Create a writeback register dummy placeholder.
3975 Inst.addOperand(MCOperand::CreateImm(0));
3976 // Rt, Rt2
3977 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3978 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3979 // addr
3980 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3981 // pred
3982 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3983 return true;
3984}
3985
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003986/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3987/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3988/// when they refer multiple MIOperands inside a single one.
3989bool ARMAsmParser::
3990cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3991 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3992 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3993 // Create a writeback register dummy placeholder.
3994 Inst.addOperand(MCOperand::CreateImm(0));
3995 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3996 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3997 return true;
3998}
3999
Jim Grosbach8e048492011-08-19 22:07:46 +00004000/// cvtThumbMultiple- Convert parsed operands to MCInst.
4001/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4002/// when they refer multiple MIOperands inside a single one.
4003bool ARMAsmParser::
4004cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4005 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4006 // The second source operand must be the same register as the destination
4007 // operand.
4008 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00004009 (((ARMOperand*)Operands[3])->getReg() !=
4010 ((ARMOperand*)Operands[5])->getReg()) &&
4011 (((ARMOperand*)Operands[3])->getReg() !=
4012 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00004013 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00004014 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00004015 return false;
4016 }
4017 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4018 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00004019 // If we have a three-operand form, make sure to set Rn to be the operand
4020 // that isn't the same as Rd.
4021 unsigned RegOp = 4;
4022 if (Operands.size() == 6 &&
4023 ((ARMOperand*)Operands[4])->getReg() ==
4024 ((ARMOperand*)Operands[3])->getReg())
4025 RegOp = 5;
4026 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4027 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00004028 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4029
4030 return true;
4031}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00004032
Jim Grosbach3ea06572011-10-24 22:16:58 +00004033bool ARMAsmParser::
4034cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4035 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4036 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00004037 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00004038 // Create a writeback register dummy placeholder.
4039 Inst.addOperand(MCOperand::CreateImm(0));
4040 // Vn
4041 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4042 // pred
4043 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4044 return true;
4045}
4046
4047bool ARMAsmParser::
4048cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4049 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4050 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00004051 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00004052 // Create a writeback register dummy placeholder.
4053 Inst.addOperand(MCOperand::CreateImm(0));
4054 // Vn
4055 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4056 // Vm
4057 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4058 // pred
4059 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4060 return true;
4061}
4062
Jim Grosbach05df4602011-10-31 21:50:31 +00004063bool ARMAsmParser::
4064cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4065 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4066 // Create a writeback register dummy placeholder.
4067 Inst.addOperand(MCOperand::CreateImm(0));
4068 // Vn
4069 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4070 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00004071 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00004072 // pred
4073 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4074 return true;
4075}
4076
4077bool ARMAsmParser::
4078cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4079 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4080 // Create a writeback register dummy placeholder.
4081 Inst.addOperand(MCOperand::CreateImm(0));
4082 // Vn
4083 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4084 // Vm
4085 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4086 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00004087 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00004088 // pred
4089 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4090 return true;
4091}
4092
Bill Wendlinge18980a2010-11-06 22:36:58 +00004093/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004094/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00004095bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00004096parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004097 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00004098 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00004099 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004100 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004101 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004102
Sean Callanan936b0d32010-01-19 21:44:56 +00004103 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004104 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00004105 if (BaseRegNum == -1)
4106 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004107
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004108 // The next token must either be a comma or a closing bracket.
4109 const AsmToken &Tok = Parser.getTok();
4110 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00004111 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004112
Jim Grosbachd3595712011-08-03 23:50:40 +00004113 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004114 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004115 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004116
Jim Grosbachd3595712011-08-03 23:50:40 +00004117 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004118 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00004119
Jim Grosbach40700e02011-09-19 18:42:21 +00004120 // If there's a pre-indexing writeback marker, '!', just add it as a token
4121 // operand. It's rather odd, but syntactically valid.
4122 if (Parser.getTok().is(AsmToken::Exclaim)) {
4123 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4124 Parser.Lex(); // Eat the '!'.
4125 }
4126
Jim Grosbachd3595712011-08-03 23:50:40 +00004127 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004128 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004129
Jim Grosbachd3595712011-08-03 23:50:40 +00004130 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4131 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004132
Jim Grosbacha95ec992011-10-11 17:29:55 +00004133 // If we have a ':', it's an alignment specifier.
4134 if (Parser.getTok().is(AsmToken::Colon)) {
4135 Parser.Lex(); // Eat the ':'.
4136 E = Parser.getTok().getLoc();
4137
4138 const MCExpr *Expr;
4139 if (getParser().ParseExpression(Expr))
4140 return true;
4141
4142 // The expression has to be a constant. Memory references with relocations
4143 // don't come through here, as they use the <label> forms of the relevant
4144 // instructions.
4145 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4146 if (!CE)
4147 return Error (E, "constant expression expected");
4148
4149 unsigned Align = 0;
4150 switch (CE->getValue()) {
4151 default:
Jim Grosbachcef98cd2011-12-19 18:31:43 +00004152 return Error(E,
4153 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4154 case 16: Align = 2; break;
4155 case 32: Align = 4; break;
Jim Grosbacha95ec992011-10-11 17:29:55 +00004156 case 64: Align = 8; break;
4157 case 128: Align = 16; break;
4158 case 256: Align = 32; break;
4159 }
4160
4161 // Now we should have the closing ']'
4162 E = Parser.getTok().getLoc();
4163 if (Parser.getTok().isNot(AsmToken::RBrac))
4164 return Error(E, "']' expected");
4165 Parser.Lex(); // Eat right bracket token.
4166
4167 // Don't worry about range checking the value here. That's handled by
4168 // the is*() predicates.
4169 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4170 ARM_AM::no_shift, 0, Align,
4171 false, S, E));
4172
4173 // If there's a pre-indexing writeback marker, '!', just add it as a token
4174 // operand.
4175 if (Parser.getTok().is(AsmToken::Exclaim)) {
4176 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4177 Parser.Lex(); // Eat the '!'.
4178 }
4179
4180 return false;
4181 }
4182
4183 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00004184 // offset. Be friendly and also accept a plain integer (without a leading
4185 // hash) for gas compatibility.
4186 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004187 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00004188 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004189 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00004190 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00004191 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004192
Owen Anderson967674d2011-08-29 19:36:44 +00004193 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00004194 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004195 if (getParser().ParseExpression(Offset))
4196 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004197
4198 // The expression has to be a constant. Memory references with relocations
4199 // don't come through here, as they use the <label> forms of the relevant
4200 // instructions.
4201 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4202 if (!CE)
4203 return Error (E, "constant expression expected");
4204
Owen Anderson967674d2011-08-29 19:36:44 +00004205 // If the constant was #-0, represent it as INT32_MIN.
4206 int32_t Val = CE->getValue();
4207 if (isNegative && Val == 0)
4208 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4209
Jim Grosbachd3595712011-08-03 23:50:40 +00004210 // Now we should have the closing ']'
4211 E = Parser.getTok().getLoc();
4212 if (Parser.getTok().isNot(AsmToken::RBrac))
4213 return Error(E, "']' expected");
4214 Parser.Lex(); // Eat right bracket token.
4215
4216 // Don't worry about range checking the value here. That's handled by
4217 // the is*() predicates.
4218 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004219 ARM_AM::no_shift, 0, 0,
4220 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004221
4222 // If there's a pre-indexing writeback marker, '!', just add it as a token
4223 // operand.
4224 if (Parser.getTok().is(AsmToken::Exclaim)) {
4225 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4226 Parser.Lex(); // Eat the '!'.
4227 }
4228
4229 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004230 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004231
4232 // The register offset is optionally preceded by a '+' or '-'
4233 bool isNegative = false;
4234 if (Parser.getTok().is(AsmToken::Minus)) {
4235 isNegative = true;
4236 Parser.Lex(); // Eat the '-'.
4237 } else if (Parser.getTok().is(AsmToken::Plus)) {
4238 // Nothing to do.
4239 Parser.Lex(); // Eat the '+'.
4240 }
4241
4242 E = Parser.getTok().getLoc();
4243 int OffsetRegNum = tryParseRegister();
4244 if (OffsetRegNum == -1)
4245 return Error(E, "register expected");
4246
4247 // If there's a shift operator, handle it.
4248 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004249 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004250 if (Parser.getTok().is(AsmToken::Comma)) {
4251 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004252 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004253 return true;
4254 }
4255
4256 // Now we should have the closing ']'
4257 E = Parser.getTok().getLoc();
4258 if (Parser.getTok().isNot(AsmToken::RBrac))
4259 return Error(E, "']' expected");
4260 Parser.Lex(); // Eat right bracket token.
4261
4262 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004263 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004264 S, E));
4265
Jim Grosbachc320c852011-08-05 21:28:30 +00004266 // If there's a pre-indexing writeback marker, '!', just add it as a token
4267 // operand.
4268 if (Parser.getTok().is(AsmToken::Exclaim)) {
4269 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4270 Parser.Lex(); // Eat the '!'.
4271 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004272
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004273 return false;
4274}
4275
Jim Grosbachd3595712011-08-03 23:50:40 +00004276/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004277/// ( lsl | lsr | asr | ror ) , # shift_amount
4278/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004279/// return true if it parses a shift otherwise it returns false.
4280bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4281 unsigned &Amount) {
4282 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004283 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004284 if (Tok.isNot(AsmToken::Identifier))
4285 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004286 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004287 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4288 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004289 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004290 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004291 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004292 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004293 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004294 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004295 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004296 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004297 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004298 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004299 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004300 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004301
Jim Grosbachd3595712011-08-03 23:50:40 +00004302 // rrx stands alone.
4303 Amount = 0;
4304 if (St != ARM_AM::rrx) {
4305 Loc = Parser.getTok().getLoc();
4306 // A '#' and a shift amount.
4307 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004308 if (HashTok.isNot(AsmToken::Hash) &&
4309 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004310 return Error(HashTok.getLoc(), "'#' expected");
4311 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004312
Jim Grosbachd3595712011-08-03 23:50:40 +00004313 const MCExpr *Expr;
4314 if (getParser().ParseExpression(Expr))
4315 return true;
4316 // Range check the immediate.
4317 // lsl, ror: 0 <= imm <= 31
4318 // lsr, asr: 0 <= imm <= 32
4319 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4320 if (!CE)
4321 return Error(Loc, "shift amount must be an immediate");
4322 int64_t Imm = CE->getValue();
4323 if (Imm < 0 ||
4324 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4325 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4326 return Error(Loc, "immediate shift value out of range");
4327 Amount = Imm;
4328 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004329
4330 return false;
4331}
4332
Jim Grosbache7fbce72011-10-03 23:38:36 +00004333/// parseFPImm - A floating point immediate expression operand.
4334ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4335parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004336 // Anything that can accept a floating point constant as an operand
4337 // needs to go through here, as the regular ParseExpression is
4338 // integer only.
4339 //
4340 // This routine still creates a generic Immediate operand, containing
4341 // a bitcast of the 64-bit floating point value. The various operands
4342 // that accept floats can check whether the value is valid for them
4343 // via the standard is*() predicates.
4344
Jim Grosbache7fbce72011-10-03 23:38:36 +00004345 SMLoc S = Parser.getTok().getLoc();
4346
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004347 if (Parser.getTok().isNot(AsmToken::Hash) &&
4348 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004349 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004350
4351 // Disambiguate the VMOV forms that can accept an FP immediate.
4352 // vmov.f32 <sreg>, #imm
4353 // vmov.f64 <dreg>, #imm
4354 // vmov.f32 <dreg>, #imm @ vector f32x2
4355 // vmov.f32 <qreg>, #imm @ vector f32x4
4356 //
4357 // There are also the NEON VMOV instructions which expect an
4358 // integer constant. Make sure we don't try to parse an FPImm
4359 // for these:
4360 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4361 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4362 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4363 TyOp->getToken() != ".f64"))
4364 return MatchOperand_NoMatch;
4365
Jim Grosbache7fbce72011-10-03 23:38:36 +00004366 Parser.Lex(); // Eat the '#'.
4367
4368 // Handle negation, as that still comes through as a separate token.
4369 bool isNegative = false;
4370 if (Parser.getTok().is(AsmToken::Minus)) {
4371 isNegative = true;
4372 Parser.Lex();
4373 }
4374 const AsmToken &Tok = Parser.getTok();
Jim Grosbach235c8d22012-01-19 02:47:30 +00004375 SMLoc Loc = Tok.getLoc();
Jim Grosbache7fbce72011-10-03 23:38:36 +00004376 if (Tok.is(AsmToken::Real)) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004377 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbache7fbce72011-10-03 23:38:36 +00004378 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4379 // If we had a '-' in front, toggle the sign bit.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004380 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbache7fbce72011-10-03 23:38:36 +00004381 Parser.Lex(); // Eat the token.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004382 Operands.push_back(ARMOperand::CreateImm(
4383 MCConstantExpr::Create(IntVal, getContext()),
4384 S, Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004385 return MatchOperand_Success;
4386 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004387 // Also handle plain integers. Instructions which allow floating point
4388 // immediates also allow a raw encoded 8-bit value.
Jim Grosbache7fbce72011-10-03 23:38:36 +00004389 if (Tok.is(AsmToken::Integer)) {
4390 int64_t Val = Tok.getIntVal();
4391 Parser.Lex(); // Eat the token.
4392 if (Val > 255 || Val < 0) {
Jim Grosbach235c8d22012-01-19 02:47:30 +00004393 Error(Loc, "encoded floating point value out of range");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004394 return MatchOperand_ParseFail;
4395 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004396 double RealVal = ARM_AM::getFPImmFloat(Val);
4397 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4398 Operands.push_back(ARMOperand::CreateImm(
4399 MCConstantExpr::Create(Val, getContext()), S,
4400 Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004401 return MatchOperand_Success;
4402 }
4403
Jim Grosbach235c8d22012-01-19 02:47:30 +00004404 Error(Loc, "invalid floating point immediate");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004405 return MatchOperand_ParseFail;
4406}
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004407
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004408/// Parse a arm instruction operand. For now this parses the operand regardless
4409/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004410bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004411 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004412 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004413
4414 // Check if the current operand has a custom associated parser, if so, try to
4415 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004416 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4417 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004418 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004419 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4420 // there was a match, but an error occurred, in which case, just return that
4421 // the operand parsing failed.
4422 if (ResTy == MatchOperand_ParseFail)
4423 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004424
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004425 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004426 default:
4427 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004428 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004429 case AsmToken::Identifier: {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004430 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004431 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004432 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004433 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004434 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004435 else if (Res == -1) // irrecoverable error
4436 return true;
Jim Grosbach4eda1452011-12-20 22:26:38 +00004437 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004438 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4439 S = Parser.getTok().getLoc();
4440 Parser.Lex();
4441 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4442 return false;
4443 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004444
4445 // Fall though for the Identifier case that is not a register or a
4446 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004447 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004448 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004449 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004450 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004451 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004452 // This was not a register so parse other operands that start with an
4453 // identifier (like labels) as expressions and create them as immediates.
4454 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004455 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004456 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004457 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004458 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004459 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4460 return false;
4461 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004462 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004463 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004464 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004465 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004466 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004467 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004468 // #42 -> immediate.
4469 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004470 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004471 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004472 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004473 const MCExpr *ImmVal;
4474 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004475 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004476 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004477 if (CE) {
4478 int32_t Val = CE->getValue();
4479 if (isNegative && Val == 0)
4480 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004481 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004482 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004483 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4484 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004485 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004486 case AsmToken::Colon: {
4487 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004488 // FIXME: Check it's an expression prefix,
4489 // e.g. (FOO - :lower16:BAR) isn't legal.
4490 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004491 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004492 return true;
4493
Evan Cheng965b3c72011-01-13 07:58:56 +00004494 const MCExpr *SubExprVal;
4495 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004496 return true;
4497
Evan Cheng965b3c72011-01-13 07:58:56 +00004498 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4499 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004500 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004501 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004502 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004503 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004504 }
4505}
4506
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004507// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004508// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004509bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004510 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004511
4512 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004513 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004514 Parser.Lex(); // Eat ':'
4515
4516 if (getLexer().isNot(AsmToken::Identifier)) {
4517 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4518 return true;
4519 }
4520
4521 StringRef IDVal = Parser.getTok().getIdentifier();
4522 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004523 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004524 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004525 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004526 } else {
4527 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4528 return true;
4529 }
4530 Parser.Lex();
4531
4532 if (getLexer().isNot(AsmToken::Colon)) {
4533 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4534 return true;
4535 }
4536 Parser.Lex(); // Eat the last ':'
4537 return false;
4538}
4539
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004540/// \brief Given a mnemonic, split out possible predication code and carry
4541/// setting letters to form a canonical mnemonic and flags.
4542//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004543// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004544// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004545StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004546 unsigned &PredicationCode,
4547 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004548 unsigned &ProcessorIMod,
4549 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004550 PredicationCode = ARMCC::AL;
4551 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004552 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004553
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004554 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004555 //
4556 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004557 if ((Mnemonic == "movs" && isThumb()) ||
4558 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4559 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4560 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4561 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4562 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4563 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004564 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4565 Mnemonic == "fmuls")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004566 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004567
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004568 // First, split out any predication code. Ignore mnemonics we know aren't
4569 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004570 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004571 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004572 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004573 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004574 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4575 .Case("eq", ARMCC::EQ)
4576 .Case("ne", ARMCC::NE)
4577 .Case("hs", ARMCC::HS)
4578 .Case("cs", ARMCC::HS)
4579 .Case("lo", ARMCC::LO)
4580 .Case("cc", ARMCC::LO)
4581 .Case("mi", ARMCC::MI)
4582 .Case("pl", ARMCC::PL)
4583 .Case("vs", ARMCC::VS)
4584 .Case("vc", ARMCC::VC)
4585 .Case("hi", ARMCC::HI)
4586 .Case("ls", ARMCC::LS)
4587 .Case("ge", ARMCC::GE)
4588 .Case("lt", ARMCC::LT)
4589 .Case("gt", ARMCC::GT)
4590 .Case("le", ARMCC::LE)
4591 .Case("al", ARMCC::AL)
4592 .Default(~0U);
4593 if (CC != ~0U) {
4594 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4595 PredicationCode = CC;
4596 }
Bill Wendling193961b2010-10-29 23:50:21 +00004597 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004598
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004599 // Next, determine if we have a carry setting bit. We explicitly ignore all
4600 // the instructions we know end in 's'.
4601 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004602 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004603 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4604 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4605 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004606 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004607 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach92a939a2011-12-19 19:02:41 +00004608 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach489ed592011-12-22 19:20:45 +00004609 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004610 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004611 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4612 CarrySetting = true;
4613 }
4614
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004615 // The "cps" instruction can have a interrupt mode operand which is glued into
4616 // the mnemonic. Check if this is the case, split it and parse the imod op
4617 if (Mnemonic.startswith("cps")) {
4618 // Split out any imod code.
4619 unsigned IMod =
4620 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4621 .Case("ie", ARM_PROC::IE)
4622 .Case("id", ARM_PROC::ID)
4623 .Default(~0U);
4624 if (IMod != ~0U) {
4625 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4626 ProcessorIMod = IMod;
4627 }
4628 }
4629
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004630 // The "it" instruction has the condition mask on the end of the mnemonic.
4631 if (Mnemonic.startswith("it")) {
4632 ITMask = Mnemonic.slice(2, Mnemonic.size());
4633 Mnemonic = Mnemonic.slice(0, 2);
4634 }
4635
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004636 return Mnemonic;
4637}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004638
4639/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4640/// inclusion of carry set or predication code operands.
4641//
4642// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004643void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004644getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004645 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004646 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4647 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004648 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004649 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004650 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004651 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004652 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004653 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004654 Mnemonic == "mla" || Mnemonic == "smlal" ||
4655 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004656 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004657 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004658 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004659
Daniel Dunbar09264122011-01-11 19:06:29 +00004660 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4661 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4662 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4663 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004664 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4665 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004666 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004667 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4668 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4669 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004670 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4671 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004672 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004673 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004674 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004675 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004676
Jim Grosbach6c45b752011-09-16 16:39:25 +00004677 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004678 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004679 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004680 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004681 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004682}
4683
Jim Grosbach7283da92011-08-16 21:12:37 +00004684bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4685 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004686 // FIXME: This is all horribly hacky. We really need a better way to deal
4687 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004688
4689 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4690 // another does not. Specifically, the MOVW instruction does not. So we
4691 // special case it here and remove the defaulted (non-setting) cc_out
4692 // operand if that's the instruction we're trying to match.
4693 //
4694 // We do this as post-processing of the explicit operands rather than just
4695 // conditionally adding the cc_out in the first place because we need
4696 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004697 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004698 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4699 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4700 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4701 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004702
4703 // Register-register 'add' for thumb does not have a cc_out operand
4704 // when there are only two register operands.
4705 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4706 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4707 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4708 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4709 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004710 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004711 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4712 // have to check the immediate range here since Thumb2 has a variant
4713 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004714 if (((isThumb() && Mnemonic == "add") ||
4715 (isThumbTwo() && Mnemonic == "sub")) &&
4716 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004717 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4718 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4719 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004720 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4721 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4722 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004723 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004724 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4725 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004726 // selecting via the generic "add" mnemonic, so to know that we
4727 // should remove the cc_out operand, we have to explicitly check that
4728 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004729 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4730 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004731 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4732 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4733 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4734 // Nest conditions rather than one big 'if' statement for readability.
4735 //
4736 // If either register is a high reg, it's either one of the SP
4737 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004738 // check against T3. If the second register is the PC, this is an
4739 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004740 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4741 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004742 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004743 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4744 return false;
4745 // If both registers are low, we're in an IT block, and the immediate is
4746 // in range, we should use encoding T1 instead, which has a cc_out.
4747 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004748 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004749 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4750 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4751 return false;
4752
4753 // Otherwise, we use encoding T4, which does not have a cc_out
4754 // operand.
4755 return true;
4756 }
4757
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004758 // The thumb2 multiply instruction doesn't have a CCOut register, so
4759 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4760 // use the 16-bit encoding or not.
4761 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4762 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4763 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4764 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4765 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4766 // If the registers aren't low regs, the destination reg isn't the
4767 // same as one of the source regs, or the cc_out operand is zero
4768 // outside of an IT block, we have to use the 32-bit encoding, so
4769 // remove the cc_out operand.
4770 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4771 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004772 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004773 !inITBlock() ||
4774 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4775 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4776 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4777 static_cast<ARMOperand*>(Operands[4])->getReg())))
4778 return true;
4779
Jim Grosbachefa7e952011-11-15 19:55:16 +00004780 // Also check the 'mul' syntax variant that doesn't specify an explicit
4781 // destination register.
4782 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4783 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4784 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4785 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4786 // If the registers aren't low regs or the cc_out operand is zero
4787 // outside of an IT block, we have to use the 32-bit encoding, so
4788 // remove the cc_out operand.
4789 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4790 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4791 !inITBlock()))
4792 return true;
4793
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004794
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004795
Jim Grosbach4b701af2011-08-24 21:42:27 +00004796 // Register-register 'add/sub' for thumb does not have a cc_out operand
4797 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4798 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4799 // right, this will result in better diagnostics (which operand is off)
4800 // anyway.
4801 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4802 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004803 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4804 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4805 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4806 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004807
Jim Grosbach7283da92011-08-16 21:12:37 +00004808 return false;
4809}
4810
Jim Grosbach12952fe2011-11-11 23:08:10 +00004811static bool isDataTypeToken(StringRef Tok) {
4812 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4813 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4814 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4815 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4816 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4817 Tok == ".f" || Tok == ".d";
4818}
4819
4820// FIXME: This bit should probably be handled via an explicit match class
4821// in the .td files that matches the suffix instead of having it be
4822// a literal string token the way it is now.
4823static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4824 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4825}
4826
Jim Grosbach8be2f652011-12-09 23:34:09 +00004827static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004828/// Parse an arm instruction mnemonic followed by its operands.
4829bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4830 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004831 // Apply mnemonic aliases before doing anything else, as the destination
4832 // mnemnonic may include suffices and we want to handle them normally.
4833 // The generic tblgen'erated code does this later, at the start of
4834 // MatchInstructionImpl(), but that's too late for aliases that include
4835 // any sort of suffix.
4836 unsigned AvailableFeatures = getAvailableFeatures();
4837 applyMnemonicAliases(Name, AvailableFeatures);
4838
Jim Grosbachab5830e2011-12-14 02:16:11 +00004839 // First check for the ARM-specific .req directive.
4840 if (Parser.getTok().is(AsmToken::Identifier) &&
4841 Parser.getTok().getIdentifier() == ".req") {
4842 parseDirectiveReq(Name, NameLoc);
4843 // We always return 'error' for this, as we're done with this
4844 // statement and don't need to match the 'instruction."
4845 return true;
4846 }
4847
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004848 // Create the leading tokens for the mnemonic, split by '.' characters.
4849 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004850 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004851
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004852 // Split out the predication code and carry setting flag from the mnemonic.
4853 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004854 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004855 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004856 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004857 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004858 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004859
Jim Grosbach1c171b12011-08-25 17:23:55 +00004860 // In Thumb1, only the branch (B) instruction can be predicated.
4861 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4862 Parser.EatToEndOfStatement();
4863 return Error(NameLoc, "conditional execution not supported in Thumb1");
4864 }
4865
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004866 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4867
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004868 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4869 // is the mask as it will be for the IT encoding if the conditional
4870 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4871 // where the conditional bit0 is zero, the instruction post-processing
4872 // will adjust the mask accordingly.
4873 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004874 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4875 if (ITMask.size() > 3) {
4876 Parser.EatToEndOfStatement();
4877 return Error(Loc, "too many conditions on IT instruction");
4878 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004879 unsigned Mask = 8;
4880 for (unsigned i = ITMask.size(); i != 0; --i) {
4881 char pos = ITMask[i - 1];
4882 if (pos != 't' && pos != 'e') {
4883 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004884 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004885 }
4886 Mask >>= 1;
4887 if (ITMask[i - 1] == 't')
4888 Mask |= 8;
4889 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004890 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004891 }
4892
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004893 // FIXME: This is all a pretty gross hack. We should automatically handle
4894 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004895
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004896 // Next, add the CCOut and ConditionCode operands, if needed.
4897 //
4898 // For mnemonics which can ever incorporate a carry setting bit or predication
4899 // code, our matching model involves us always generating CCOut and
4900 // ConditionCode operands to match the mnemonic "as written" and then we let
4901 // the matcher deal with finding the right instruction or generating an
4902 // appropriate error.
4903 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004904 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004905
Jim Grosbach03a8a162011-07-14 22:04:21 +00004906 // If we had a carry-set on an instruction that can't do that, issue an
4907 // error.
4908 if (!CanAcceptCarrySet && CarrySetting) {
4909 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004910 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004911 "' can not set flags, but 's' suffix specified");
4912 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004913 // If we had a predication code on an instruction that can't do that, issue an
4914 // error.
4915 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4916 Parser.EatToEndOfStatement();
4917 return Error(NameLoc, "instruction '" + Mnemonic +
4918 "' is not predicable, but condition code specified");
4919 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004920
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004921 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004922 if (CanAcceptCarrySet) {
4923 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004924 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004925 Loc));
4926 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004927
4928 // Add the predication code operand, if necessary.
4929 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004930 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4931 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004932 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004933 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004934 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004935
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004936 // Add the processor imod operand, if necessary.
4937 if (ProcessorIMod) {
4938 Operands.push_back(ARMOperand::CreateImm(
4939 MCConstantExpr::Create(ProcessorIMod, getContext()),
4940 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004941 }
4942
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004943 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004944 while (Next != StringRef::npos) {
4945 Start = Next;
4946 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004947 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004948
Jim Grosbach12952fe2011-11-11 23:08:10 +00004949 // Some NEON instructions have an optional datatype suffix that is
4950 // completely ignored. Check for that.
4951 if (isDataTypeToken(ExtraToken) &&
4952 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4953 continue;
4954
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004955 if (ExtraToken != ".n") {
4956 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4957 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4958 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004959 }
4960
4961 // Read the remaining operands.
4962 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004963 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004964 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004965 Parser.EatToEndOfStatement();
4966 return true;
4967 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004968
4969 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004970 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004971
4972 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004973 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004974 Parser.EatToEndOfStatement();
4975 return true;
4976 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004977 }
4978 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004979
Chris Lattnera2a9d162010-09-11 16:18:25 +00004980 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004981 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004982 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004983 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004984 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004985
Chris Lattner91689c12010-09-08 05:10:46 +00004986 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004987
Jim Grosbach7283da92011-08-16 21:12:37 +00004988 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4989 // do and don't have a cc_out optional-def operand. With some spot-checks
4990 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004991 // parse and adjust accordingly before actually matching. We shouldn't ever
4992 // try to remove a cc_out operand that was explicitly set on the the
4993 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4994 // table driven matcher doesn't fit well with the ARM instruction set.
4995 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004996 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4997 Operands.erase(Operands.begin() + 1);
4998 delete Op;
4999 }
5000
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005001 // ARM mode 'blx' need special handling, as the register operand version
5002 // is predicable, but the label operand version is not. So, we can't rely
5003 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00005004 // a k_CondCode operand in the list. If we're trying to match the label
5005 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005006 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5007 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5008 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5009 Operands.erase(Operands.begin() + 1);
5010 delete Op;
5011 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00005012
5013 // The vector-compare-to-zero instructions have a literal token "#0" at
5014 // the end that comes to here as an immediate operand. Convert it to a
5015 // token to play nicely with the matcher.
5016 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5017 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5018 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5019 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5020 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5021 if (CE && CE->getValue() == 0) {
5022 Operands.erase(Operands.begin() + 5);
5023 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5024 delete Op;
5025 }
5026 }
Jim Grosbach46b66462011-10-03 22:30:24 +00005027 // VCMP{E} does the same thing, but with a different operand count.
5028 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5029 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5030 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5031 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5032 if (CE && CE->getValue() == 0) {
5033 Operands.erase(Operands.begin() + 4);
5034 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5035 delete Op;
5036 }
5037 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005038 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005039 // end. Convert it to a token here. Take care not to convert those
5040 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005041 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005042 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5043 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005044 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5045 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5046 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005047 if (CE && CE->getValue() == 0 &&
5048 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00005049 // The cc_out operand matches the IT block.
5050 ((inITBlock() != CarrySetting) &&
5051 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00005052 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00005053 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00005054 Operands.erase(Operands.begin() + 5);
5055 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5056 delete Op;
5057 }
5058 }
5059
Chris Lattnerf29c0b62010-01-14 22:21:20 +00005060 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00005061}
5062
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005063// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005064
5065// return 'true' if register list contains non-low GPR registers,
5066// 'false' otherwise. If Reg is in the register list or is HiReg, set
5067// 'containsReg' to true.
5068static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5069 unsigned HiReg, bool &containsReg) {
5070 containsReg = false;
5071 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5072 unsigned OpReg = Inst.getOperand(i).getReg();
5073 if (OpReg == Reg)
5074 containsReg = true;
5075 // Anything other than a low register isn't legal here.
5076 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5077 return true;
5078 }
5079 return false;
5080}
5081
Jim Grosbacha31f2232011-09-07 18:05:34 +00005082// Check if the specified regisgter is in the register list of the inst,
5083// starting at the indicated operand number.
5084static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5085 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5086 unsigned OpReg = Inst.getOperand(i).getReg();
5087 if (OpReg == Reg)
5088 return true;
5089 }
5090 return false;
5091}
5092
Jim Grosbached16ec42011-08-29 22:24:09 +00005093// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5094// the ARMInsts array) instead. Getting that here requires awkward
5095// API changes, though. Better way?
5096namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005097extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00005098}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005099static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005100 return ARMInsts[Opcode];
5101}
5102
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005103// FIXME: We would really like to be able to tablegen'erate this.
5104bool ARMAsmParser::
5105validateInstruction(MCInst &Inst,
5106 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005107 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00005108 SMLoc Loc = Operands[0]->getStartLoc();
5109 // Check the IT block state first.
Jim Grosbach82f76d12012-01-25 19:52:01 +00005110 // NOTE: BKPT instruction has the interesting property of being
5111 // allowed in IT blocks, but not being predicable. It just always
Owen Anderson44ae2da2011-09-13 17:59:19 +00005112 // executes.
Jim Grosbach82f76d12012-01-25 19:52:01 +00005113 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5114 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005115 unsigned bit = 1;
5116 if (ITState.FirstCond)
5117 ITState.FirstCond = false;
5118 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005119 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00005120 // The instruction must be predicable.
5121 if (!MCID.isPredicable())
5122 return Error(Loc, "instructions in IT block must be predicable");
5123 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5124 unsigned ITCond = bit ? ITState.Cond :
5125 ARMCC::getOppositeCondition(ITState.Cond);
5126 if (Cond != ITCond) {
5127 // Find the condition code Operand to get its SMLoc information.
5128 SMLoc CondLoc;
5129 for (unsigned i = 1; i < Operands.size(); ++i)
5130 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5131 CondLoc = Operands[i]->getStartLoc();
5132 return Error(CondLoc, "incorrect condition in IT block; got '" +
5133 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5134 "', but expected '" +
5135 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5136 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00005137 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005138 } else if (isThumbTwo() && MCID.isPredicable() &&
5139 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005140 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5141 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00005142 return Error(Loc, "predicated instructions must be in IT block");
5143
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005144 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00005145 case ARM::LDRD:
5146 case ARM::LDRD_PRE:
5147 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005148 case ARM::LDREXD: {
5149 // Rt2 must be Rt + 1.
5150 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5151 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5152 if (Rt2 != Rt + 1)
5153 return Error(Operands[3]->getStartLoc(),
5154 "destination operands must be sequential");
5155 return false;
5156 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00005157 case ARM::STRD: {
5158 // Rt2 must be Rt + 1.
5159 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5160 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5161 if (Rt2 != Rt + 1)
5162 return Error(Operands[3]->getStartLoc(),
5163 "source operands must be sequential");
5164 return false;
5165 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00005166 case ARM::STRD_PRE:
5167 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005168 case ARM::STREXD: {
5169 // Rt2 must be Rt + 1.
5170 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5171 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5172 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00005173 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005174 "source operands must be sequential");
5175 return false;
5176 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00005177 case ARM::SBFX:
5178 case ARM::UBFX: {
5179 // width must be in range [1, 32-lsb]
5180 unsigned lsb = Inst.getOperand(2).getImm();
5181 unsigned widthm1 = Inst.getOperand(3).getImm();
5182 if (widthm1 >= 32 - lsb)
5183 return Error(Operands[5]->getStartLoc(),
5184 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00005185 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00005186 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00005187 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00005188 // If we're parsing Thumb2, the .w variant is available and handles
5189 // most cases that are normally illegal for a Thumb1 LDM
5190 // instruction. We'll make the transformation in processInstruction()
5191 // if necessary.
5192 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00005193 // Thumb LDM instructions are writeback iff the base register is not
5194 // in the register list.
5195 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00005196 bool hasWritebackToken =
5197 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5198 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00005199 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005200 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005201 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5202 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005203 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00005204 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00005205 return Error(Operands[2]->getStartLoc(),
5206 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00005207 // If we should not have writeback, there must not be a '!'. This is
5208 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005209 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00005210 return Error(Operands[3]->getStartLoc(),
5211 "writeback operator '!' not allowed when base register "
5212 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005213
5214 break;
5215 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00005216 case ARM::t2LDMIA_UPD: {
5217 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5218 return Error(Operands[4]->getStartLoc(),
5219 "writeback operator '!' not allowed when base register "
5220 "in register list");
5221 break;
5222 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005223 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5224 // so only issue a diagnostic for thumb1. The instructions will be
5225 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005226 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005227 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005228 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5229 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005230 return Error(Operands[2]->getStartLoc(),
5231 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005232 break;
5233 }
5234 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005235 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005236 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5237 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005238 return Error(Operands[2]->getStartLoc(),
5239 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005240 break;
5241 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00005242 case ARM::tSTMIA_UPD: {
5243 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00005244 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00005245 return Error(Operands[4]->getStartLoc(),
5246 "registers must be in range r0-r7");
5247 break;
5248 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005249 }
5250
5251 return false;
5252}
5253
Jim Grosbach1a747242012-01-23 23:45:44 +00005254static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbacheb538222011-12-02 22:34:51 +00005255 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00005256 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005257 // VST1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005258 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5259 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5260 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5261 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5262 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5263 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5264 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5265 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5266 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005267
5268 // VST2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005269 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5270 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5271 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5272 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5273 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005274
Jim Grosbach1e946a42012-01-24 00:43:12 +00005275 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5276 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5277 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5278 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5279 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005280
Jim Grosbach1e946a42012-01-24 00:43:12 +00005281 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5282 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5283 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5284 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5285 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbach1a747242012-01-23 23:45:44 +00005286
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005287 // VST3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005288 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5289 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5290 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5291 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5292 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5293 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5294 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5295 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5296 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5297 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5298 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5299 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5300 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5301 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5302 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005303
Jim Grosbach1a747242012-01-23 23:45:44 +00005304 // VST3
Jim Grosbach1e946a42012-01-24 00:43:12 +00005305 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5306 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5307 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5308 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5309 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5310 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5311 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5312 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5313 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5314 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5315 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5316 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5317 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5318 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5319 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5320 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5321 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5322 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbachda70eac2012-01-24 00:58:13 +00005323
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005324 // VST4LN
5325 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5326 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5327 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5328 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5329 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5330 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5331 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5332 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5333 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5334 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5335 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5336 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5337 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5338 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5339 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5340
Jim Grosbachda70eac2012-01-24 00:58:13 +00005341 // VST4
5342 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5343 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5344 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5345 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5346 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5347 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5348 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5349 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5350 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5351 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5352 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5353 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5354 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5355 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5356 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5357 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5358 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5359 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005360 }
5361}
5362
Jim Grosbach1a747242012-01-23 23:45:44 +00005363static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005364 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00005365 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005366 // VLD1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005367 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5368 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5369 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5370 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5371 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5372 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5373 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5374 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5375 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005376
5377 // VLD2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005378 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5379 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5380 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5381 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5382 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5383 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5384 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5385 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5386 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5387 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5388 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5389 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5390 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5391 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5392 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005393
Jim Grosbachb78403c2012-01-24 23:47:04 +00005394 // VLD3DUP
5395 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5396 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5397 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5398 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5399 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5400 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5401 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5402 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5403 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5404 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5405 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5406 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5407 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5408 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5409 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5410 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5411 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5412 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5413
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005414 // VLD3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00005415 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5416 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5417 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5418 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5419 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5420 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5421 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5422 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5423 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5424 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5425 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5426 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5427 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5428 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5429 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005430
5431 // VLD3
Jim Grosbach1e946a42012-01-24 00:43:12 +00005432 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5433 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5434 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5435 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5436 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5437 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5438 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5439 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5440 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5441 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5442 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5443 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5444 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5445 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5446 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5447 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5448 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5449 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbached561fc2012-01-24 00:43:17 +00005450
Jim Grosbach14952a02012-01-24 18:37:25 +00005451 // VLD4LN
5452 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5453 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5454 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5455 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5456 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5457 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5458 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5459 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5460 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5461 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5462 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5463 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5464 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5465 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5466 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5467
Jim Grosbach086cbfa2012-01-25 00:01:08 +00005468 // VLD4DUP
5469 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5470 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5471 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5472 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5473 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5474 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5475 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5476 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5477 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5478 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5479 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5480 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5481 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5482 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5483 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5484 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5485 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5486 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5487
Jim Grosbached561fc2012-01-24 00:43:17 +00005488 // VLD4
5489 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5490 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5491 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5492 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5493 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5494 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5495 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5496 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5497 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5498 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5499 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5500 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5501 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5502 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5503 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5504 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5505 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5506 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005507 }
5508}
5509
Jim Grosbachafad0532011-11-10 23:42:14 +00005510bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005511processInstruction(MCInst &Inst,
5512 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5513 switch (Inst.getOpcode()) {
Jim Grosbach94298a92012-01-18 22:46:46 +00005514 // Aliases for alternate PC+imm syntax of LDR instructions.
5515 case ARM::t2LDRpcrel:
5516 Inst.setOpcode(ARM::t2LDRpci);
5517 return true;
5518 case ARM::t2LDRBpcrel:
5519 Inst.setOpcode(ARM::t2LDRBpci);
5520 return true;
5521 case ARM::t2LDRHpcrel:
5522 Inst.setOpcode(ARM::t2LDRHpci);
5523 return true;
5524 case ARM::t2LDRSBpcrel:
5525 Inst.setOpcode(ARM::t2LDRSBpci);
5526 return true;
5527 case ARM::t2LDRSHpcrel:
5528 Inst.setOpcode(ARM::t2LDRSHpci);
5529 return true;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005530 // Handle NEON VST complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005531 case ARM::VST1LNdWB_register_Asm_8:
5532 case ARM::VST1LNdWB_register_Asm_16:
5533 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005534 MCInst TmpInst;
5535 // Shuffle the operands around so the lane index operand is in the
5536 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005537 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005538 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005539 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5540 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5541 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5542 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5543 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5544 TmpInst.addOperand(Inst.getOperand(1)); // lane
5545 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5546 TmpInst.addOperand(Inst.getOperand(6));
5547 Inst = TmpInst;
5548 return true;
5549 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005550
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005551 case ARM::VST2LNdWB_register_Asm_8:
5552 case ARM::VST2LNdWB_register_Asm_16:
5553 case ARM::VST2LNdWB_register_Asm_32:
5554 case ARM::VST2LNqWB_register_Asm_16:
5555 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005556 MCInst TmpInst;
5557 // Shuffle the operands around so the lane index operand is in the
5558 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005559 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005560 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005561 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5562 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5563 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5564 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5565 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005566 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5567 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005568 TmpInst.addOperand(Inst.getOperand(1)); // lane
5569 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5570 TmpInst.addOperand(Inst.getOperand(6));
5571 Inst = TmpInst;
5572 return true;
5573 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005574
5575 case ARM::VST3LNdWB_register_Asm_8:
5576 case ARM::VST3LNdWB_register_Asm_16:
5577 case ARM::VST3LNdWB_register_Asm_32:
5578 case ARM::VST3LNqWB_register_Asm_16:
5579 case ARM::VST3LNqWB_register_Asm_32: {
5580 MCInst TmpInst;
5581 // Shuffle the operands around so the lane index operand is in the
5582 // right place.
5583 unsigned Spacing;
5584 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5585 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5586 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5587 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5588 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5589 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5590 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5591 Spacing));
5592 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5593 Spacing * 2));
5594 TmpInst.addOperand(Inst.getOperand(1)); // lane
5595 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5596 TmpInst.addOperand(Inst.getOperand(6));
5597 Inst = TmpInst;
5598 return true;
5599 }
5600
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005601 case ARM::VST4LNdWB_register_Asm_8:
5602 case ARM::VST4LNdWB_register_Asm_16:
5603 case ARM::VST4LNdWB_register_Asm_32:
5604 case ARM::VST4LNqWB_register_Asm_16:
5605 case ARM::VST4LNqWB_register_Asm_32: {
5606 MCInst TmpInst;
5607 // Shuffle the operands around so the lane index operand is in the
5608 // right place.
5609 unsigned Spacing;
5610 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5611 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5612 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5613 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5614 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5615 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5616 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5617 Spacing));
5618 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5619 Spacing * 2));
5620 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5621 Spacing * 3));
5622 TmpInst.addOperand(Inst.getOperand(1)); // lane
5623 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5624 TmpInst.addOperand(Inst.getOperand(6));
5625 Inst = TmpInst;
5626 return true;
5627 }
5628
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005629 case ARM::VST1LNdWB_fixed_Asm_8:
5630 case ARM::VST1LNdWB_fixed_Asm_16:
5631 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005632 MCInst TmpInst;
5633 // Shuffle the operands around so the lane index operand is in the
5634 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005635 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005636 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005637 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5638 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5639 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5640 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5641 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5642 TmpInst.addOperand(Inst.getOperand(1)); // lane
5643 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5644 TmpInst.addOperand(Inst.getOperand(5));
5645 Inst = TmpInst;
5646 return true;
5647 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005648
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005649 case ARM::VST2LNdWB_fixed_Asm_8:
5650 case ARM::VST2LNdWB_fixed_Asm_16:
5651 case ARM::VST2LNdWB_fixed_Asm_32:
5652 case ARM::VST2LNqWB_fixed_Asm_16:
5653 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005654 MCInst TmpInst;
5655 // Shuffle the operands around so the lane index operand is in the
5656 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005657 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005658 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005659 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5660 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5661 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5662 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5663 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005664 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5665 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005666 TmpInst.addOperand(Inst.getOperand(1)); // lane
5667 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5668 TmpInst.addOperand(Inst.getOperand(5));
5669 Inst = TmpInst;
5670 return true;
5671 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005672
5673 case ARM::VST3LNdWB_fixed_Asm_8:
5674 case ARM::VST3LNdWB_fixed_Asm_16:
5675 case ARM::VST3LNdWB_fixed_Asm_32:
5676 case ARM::VST3LNqWB_fixed_Asm_16:
5677 case ARM::VST3LNqWB_fixed_Asm_32: {
5678 MCInst TmpInst;
5679 // Shuffle the operands around so the lane index operand is in the
5680 // right place.
5681 unsigned Spacing;
5682 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5683 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5684 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5685 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5686 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5687 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5688 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5689 Spacing));
5690 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5691 Spacing * 2));
5692 TmpInst.addOperand(Inst.getOperand(1)); // lane
5693 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5694 TmpInst.addOperand(Inst.getOperand(5));
5695 Inst = TmpInst;
5696 return true;
5697 }
5698
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005699 case ARM::VST4LNdWB_fixed_Asm_8:
5700 case ARM::VST4LNdWB_fixed_Asm_16:
5701 case ARM::VST4LNdWB_fixed_Asm_32:
5702 case ARM::VST4LNqWB_fixed_Asm_16:
5703 case ARM::VST4LNqWB_fixed_Asm_32: {
5704 MCInst TmpInst;
5705 // Shuffle the operands around so the lane index operand is in the
5706 // right place.
5707 unsigned Spacing;
5708 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5709 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5710 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5711 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5712 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5713 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5714 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5715 Spacing));
5716 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5717 Spacing * 2));
5718 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5719 Spacing * 3));
5720 TmpInst.addOperand(Inst.getOperand(1)); // lane
5721 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5722 TmpInst.addOperand(Inst.getOperand(5));
5723 Inst = TmpInst;
5724 return true;
5725 }
5726
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005727 case ARM::VST1LNdAsm_8:
5728 case ARM::VST1LNdAsm_16:
5729 case ARM::VST1LNdAsm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005730 MCInst TmpInst;
5731 // Shuffle the operands around so the lane index operand is in the
5732 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005733 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005734 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005735 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5736 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5737 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5738 TmpInst.addOperand(Inst.getOperand(1)); // lane
5739 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5740 TmpInst.addOperand(Inst.getOperand(5));
5741 Inst = TmpInst;
5742 return true;
5743 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005744
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005745 case ARM::VST2LNdAsm_8:
5746 case ARM::VST2LNdAsm_16:
5747 case ARM::VST2LNdAsm_32:
5748 case ARM::VST2LNqAsm_16:
5749 case ARM::VST2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005750 MCInst TmpInst;
5751 // Shuffle the operands around so the lane index operand is in the
5752 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005753 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005754 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005755 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5756 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5757 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005758 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5759 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005760 TmpInst.addOperand(Inst.getOperand(1)); // lane
5761 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5762 TmpInst.addOperand(Inst.getOperand(5));
5763 Inst = TmpInst;
5764 return true;
5765 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00005766
5767 case ARM::VST3LNdAsm_8:
5768 case ARM::VST3LNdAsm_16:
5769 case ARM::VST3LNdAsm_32:
5770 case ARM::VST3LNqAsm_16:
5771 case ARM::VST3LNqAsm_32: {
5772 MCInst TmpInst;
5773 // Shuffle the operands around so the lane index operand is in the
5774 // right place.
5775 unsigned Spacing;
5776 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5777 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5778 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5779 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5780 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5781 Spacing));
5782 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5783 Spacing * 2));
5784 TmpInst.addOperand(Inst.getOperand(1)); // lane
5785 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5786 TmpInst.addOperand(Inst.getOperand(5));
5787 Inst = TmpInst;
5788 return true;
5789 }
5790
Jim Grosbach8e2722c2012-01-24 18:53:13 +00005791 case ARM::VST4LNdAsm_8:
5792 case ARM::VST4LNdAsm_16:
5793 case ARM::VST4LNdAsm_32:
5794 case ARM::VST4LNqAsm_16:
5795 case ARM::VST4LNqAsm_32: {
5796 MCInst TmpInst;
5797 // Shuffle the operands around so the lane index operand is in the
5798 // right place.
5799 unsigned Spacing;
5800 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5801 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5802 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5803 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5804 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5805 Spacing));
5806 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5807 Spacing * 2));
5808 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5809 Spacing * 3));
5810 TmpInst.addOperand(Inst.getOperand(1)); // lane
5811 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5812 TmpInst.addOperand(Inst.getOperand(5));
5813 Inst = TmpInst;
5814 return true;
5815 }
5816
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005817 // Handle NEON VLD complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005818 case ARM::VLD1LNdWB_register_Asm_8:
5819 case ARM::VLD1LNdWB_register_Asm_16:
5820 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005821 MCInst TmpInst;
5822 // Shuffle the operands around so the lane index operand is in the
5823 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005824 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005825 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005826 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5827 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5828 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5829 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5830 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5831 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5832 TmpInst.addOperand(Inst.getOperand(1)); // lane
5833 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5834 TmpInst.addOperand(Inst.getOperand(6));
5835 Inst = TmpInst;
5836 return true;
5837 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005838
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005839 case ARM::VLD2LNdWB_register_Asm_8:
5840 case ARM::VLD2LNdWB_register_Asm_16:
5841 case ARM::VLD2LNdWB_register_Asm_32:
5842 case ARM::VLD2LNqWB_register_Asm_16:
5843 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005844 MCInst TmpInst;
5845 // Shuffle the operands around so the lane index operand is in the
5846 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005847 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005848 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005849 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005850 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5851 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005852 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5853 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5854 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5855 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5856 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005857 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5858 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005859 TmpInst.addOperand(Inst.getOperand(1)); // lane
5860 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5861 TmpInst.addOperand(Inst.getOperand(6));
5862 Inst = TmpInst;
5863 return true;
5864 }
5865
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005866 case ARM::VLD3LNdWB_register_Asm_8:
5867 case ARM::VLD3LNdWB_register_Asm_16:
5868 case ARM::VLD3LNdWB_register_Asm_32:
5869 case ARM::VLD3LNqWB_register_Asm_16:
5870 case ARM::VLD3LNqWB_register_Asm_32: {
5871 MCInst TmpInst;
5872 // Shuffle the operands around so the lane index operand is in the
5873 // right place.
5874 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005875 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005876 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5877 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5878 Spacing));
5879 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005880 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005881 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5882 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5883 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5884 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5885 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5886 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5887 Spacing));
5888 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005889 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005890 TmpInst.addOperand(Inst.getOperand(1)); // lane
5891 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5892 TmpInst.addOperand(Inst.getOperand(6));
5893 Inst = TmpInst;
5894 return true;
5895 }
5896
Jim Grosbach14952a02012-01-24 18:37:25 +00005897 case ARM::VLD4LNdWB_register_Asm_8:
5898 case ARM::VLD4LNdWB_register_Asm_16:
5899 case ARM::VLD4LNdWB_register_Asm_32:
5900 case ARM::VLD4LNqWB_register_Asm_16:
5901 case ARM::VLD4LNqWB_register_Asm_32: {
5902 MCInst TmpInst;
5903 // Shuffle the operands around so the lane index operand is in the
5904 // right place.
5905 unsigned Spacing;
5906 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5907 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5908 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5909 Spacing));
5910 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5911 Spacing * 2));
5912 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5913 Spacing * 3));
5914 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5915 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5916 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5917 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5918 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5919 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5920 Spacing));
5921 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5922 Spacing * 2));
5923 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5924 Spacing * 3));
5925 TmpInst.addOperand(Inst.getOperand(1)); // lane
5926 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5927 TmpInst.addOperand(Inst.getOperand(6));
5928 Inst = TmpInst;
5929 return true;
5930 }
5931
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005932 case ARM::VLD1LNdWB_fixed_Asm_8:
5933 case ARM::VLD1LNdWB_fixed_Asm_16:
5934 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005935 MCInst TmpInst;
5936 // Shuffle the operands around so the lane index operand is in the
5937 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005938 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005939 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005940 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5941 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5942 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5943 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5944 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5945 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5946 TmpInst.addOperand(Inst.getOperand(1)); // lane
5947 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5948 TmpInst.addOperand(Inst.getOperand(5));
5949 Inst = TmpInst;
5950 return true;
5951 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005952
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005953 case ARM::VLD2LNdWB_fixed_Asm_8:
5954 case ARM::VLD2LNdWB_fixed_Asm_16:
5955 case ARM::VLD2LNdWB_fixed_Asm_32:
5956 case ARM::VLD2LNqWB_fixed_Asm_16:
5957 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005958 MCInst TmpInst;
5959 // Shuffle the operands around so the lane index operand is in the
5960 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005961 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005962 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005963 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005964 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5965 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005966 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5967 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5968 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5969 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5970 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005971 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5972 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005973 TmpInst.addOperand(Inst.getOperand(1)); // lane
5974 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5975 TmpInst.addOperand(Inst.getOperand(5));
5976 Inst = TmpInst;
5977 return true;
5978 }
5979
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005980 case ARM::VLD3LNdWB_fixed_Asm_8:
5981 case ARM::VLD3LNdWB_fixed_Asm_16:
5982 case ARM::VLD3LNdWB_fixed_Asm_32:
5983 case ARM::VLD3LNqWB_fixed_Asm_16:
5984 case ARM::VLD3LNqWB_fixed_Asm_32: {
5985 MCInst TmpInst;
5986 // Shuffle the operands around so the lane index operand is in the
5987 // right place.
5988 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00005989 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005990 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5991 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5992 Spacing));
5993 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00005994 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005995 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5996 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5997 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5998 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5999 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6000 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6001 Spacing));
6002 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006003 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006004 TmpInst.addOperand(Inst.getOperand(1)); // lane
6005 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6006 TmpInst.addOperand(Inst.getOperand(5));
6007 Inst = TmpInst;
6008 return true;
6009 }
6010
Jim Grosbach14952a02012-01-24 18:37:25 +00006011 case ARM::VLD4LNdWB_fixed_Asm_8:
6012 case ARM::VLD4LNdWB_fixed_Asm_16:
6013 case ARM::VLD4LNdWB_fixed_Asm_32:
6014 case ARM::VLD4LNqWB_fixed_Asm_16:
6015 case ARM::VLD4LNqWB_fixed_Asm_32: {
6016 MCInst TmpInst;
6017 // Shuffle the operands around so the lane index operand is in the
6018 // right place.
6019 unsigned Spacing;
6020 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6021 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6022 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6023 Spacing));
6024 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6025 Spacing * 2));
6026 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6027 Spacing * 3));
6028 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6029 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6030 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6031 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6032 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6033 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6034 Spacing));
6035 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6036 Spacing * 2));
6037 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6038 Spacing * 3));
6039 TmpInst.addOperand(Inst.getOperand(1)); // lane
6040 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6041 TmpInst.addOperand(Inst.getOperand(5));
6042 Inst = TmpInst;
6043 return true;
6044 }
6045
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006046 case ARM::VLD1LNdAsm_8:
6047 case ARM::VLD1LNdAsm_16:
6048 case ARM::VLD1LNdAsm_32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00006049 MCInst TmpInst;
6050 // Shuffle the operands around so the lane index operand is in the
6051 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006052 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006053 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach04945c42011-12-02 00:35:16 +00006054 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6055 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6056 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6057 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6058 TmpInst.addOperand(Inst.getOperand(1)); // lane
6059 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6060 TmpInst.addOperand(Inst.getOperand(5));
6061 Inst = TmpInst;
6062 return true;
6063 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006064
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006065 case ARM::VLD2LNdAsm_8:
6066 case ARM::VLD2LNdAsm_16:
6067 case ARM::VLD2LNdAsm_32:
6068 case ARM::VLD2LNqAsm_16:
6069 case ARM::VLD2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006070 MCInst TmpInst;
6071 // Shuffle the operands around so the lane index operand is in the
6072 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006073 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006074 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006075 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006076 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6077 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006078 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6079 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6080 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006081 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6082 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006083 TmpInst.addOperand(Inst.getOperand(1)); // lane
6084 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6085 TmpInst.addOperand(Inst.getOperand(5));
6086 Inst = TmpInst;
6087 return true;
6088 }
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006089
6090 case ARM::VLD3LNdAsm_8:
6091 case ARM::VLD3LNdAsm_16:
6092 case ARM::VLD3LNdAsm_32:
6093 case ARM::VLD3LNqAsm_16:
6094 case ARM::VLD3LNqAsm_32: {
6095 MCInst TmpInst;
6096 // Shuffle the operands around so the lane index operand is in the
6097 // right place.
6098 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006099 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006100 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6101 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6102 Spacing));
6103 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006104 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006105 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6106 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6107 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6108 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6109 Spacing));
6110 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006111 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006112 TmpInst.addOperand(Inst.getOperand(1)); // lane
6113 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6114 TmpInst.addOperand(Inst.getOperand(5));
6115 Inst = TmpInst;
6116 return true;
6117 }
6118
Jim Grosbach14952a02012-01-24 18:37:25 +00006119 case ARM::VLD4LNdAsm_8:
6120 case ARM::VLD4LNdAsm_16:
6121 case ARM::VLD4LNdAsm_32:
6122 case ARM::VLD4LNqAsm_16:
6123 case ARM::VLD4LNqAsm_32: {
6124 MCInst TmpInst;
6125 // Shuffle the operands around so the lane index operand is in the
6126 // right place.
6127 unsigned Spacing;
6128 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6129 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6130 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6131 Spacing));
6132 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6133 Spacing * 2));
6134 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6135 Spacing * 3));
6136 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6137 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6138 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6139 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6140 Spacing));
6141 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6142 Spacing * 2));
6143 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6144 Spacing * 3));
6145 TmpInst.addOperand(Inst.getOperand(1)); // lane
6146 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6147 TmpInst.addOperand(Inst.getOperand(5));
6148 Inst = TmpInst;
6149 return true;
6150 }
6151
Jim Grosbachb78403c2012-01-24 23:47:04 +00006152 // VLD3DUP single 3-element structure to all lanes instructions.
6153 case ARM::VLD3DUPdAsm_8:
6154 case ARM::VLD3DUPdAsm_16:
6155 case ARM::VLD3DUPdAsm_32:
6156 case ARM::VLD3DUPqAsm_8:
6157 case ARM::VLD3DUPqAsm_16:
6158 case ARM::VLD3DUPqAsm_32: {
6159 MCInst TmpInst;
6160 unsigned Spacing;
6161 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6162 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6163 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6164 Spacing));
6165 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6166 Spacing * 2));
6167 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6168 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6169 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6170 TmpInst.addOperand(Inst.getOperand(4));
6171 Inst = TmpInst;
6172 return true;
6173 }
6174
6175 case ARM::VLD3DUPdWB_fixed_Asm_8:
6176 case ARM::VLD3DUPdWB_fixed_Asm_16:
6177 case ARM::VLD3DUPdWB_fixed_Asm_32:
6178 case ARM::VLD3DUPqWB_fixed_Asm_8:
6179 case ARM::VLD3DUPqWB_fixed_Asm_16:
6180 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6181 MCInst TmpInst;
6182 unsigned Spacing;
6183 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6184 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6185 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6186 Spacing));
6187 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6188 Spacing * 2));
6189 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6190 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6191 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6192 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6193 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6194 TmpInst.addOperand(Inst.getOperand(4));
6195 Inst = TmpInst;
6196 return true;
6197 }
6198
6199 case ARM::VLD3DUPdWB_register_Asm_8:
6200 case ARM::VLD3DUPdWB_register_Asm_16:
6201 case ARM::VLD3DUPdWB_register_Asm_32:
6202 case ARM::VLD3DUPqWB_register_Asm_8:
6203 case ARM::VLD3DUPqWB_register_Asm_16:
6204 case ARM::VLD3DUPqWB_register_Asm_32: {
6205 MCInst TmpInst;
6206 unsigned Spacing;
6207 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6208 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6209 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6210 Spacing));
6211 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6212 Spacing * 2));
6213 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6214 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6215 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6216 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6217 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6218 TmpInst.addOperand(Inst.getOperand(5));
6219 Inst = TmpInst;
6220 return true;
6221 }
6222
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006223 // VLD3 multiple 3-element structure instructions.
6224 case ARM::VLD3dAsm_8:
6225 case ARM::VLD3dAsm_16:
6226 case ARM::VLD3dAsm_32:
6227 case ARM::VLD3qAsm_8:
6228 case ARM::VLD3qAsm_16:
6229 case ARM::VLD3qAsm_32: {
6230 MCInst TmpInst;
6231 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006232 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006233 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6234 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6235 Spacing));
6236 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6237 Spacing * 2));
6238 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6239 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6240 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6241 TmpInst.addOperand(Inst.getOperand(4));
6242 Inst = TmpInst;
6243 return true;
6244 }
6245
6246 case ARM::VLD3dWB_fixed_Asm_8:
6247 case ARM::VLD3dWB_fixed_Asm_16:
6248 case ARM::VLD3dWB_fixed_Asm_32:
6249 case ARM::VLD3qWB_fixed_Asm_8:
6250 case ARM::VLD3qWB_fixed_Asm_16:
6251 case ARM::VLD3qWB_fixed_Asm_32: {
6252 MCInst TmpInst;
6253 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006254 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006255 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6256 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6257 Spacing));
6258 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6259 Spacing * 2));
6260 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6261 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6262 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6263 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6264 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6265 TmpInst.addOperand(Inst.getOperand(4));
6266 Inst = TmpInst;
6267 return true;
6268 }
6269
6270 case ARM::VLD3dWB_register_Asm_8:
6271 case ARM::VLD3dWB_register_Asm_16:
6272 case ARM::VLD3dWB_register_Asm_32:
6273 case ARM::VLD3qWB_register_Asm_8:
6274 case ARM::VLD3qWB_register_Asm_16:
6275 case ARM::VLD3qWB_register_Asm_32: {
6276 MCInst TmpInst;
6277 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006278 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006279 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6280 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6281 Spacing));
6282 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6283 Spacing * 2));
6284 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6285 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6286 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6287 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6288 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6289 TmpInst.addOperand(Inst.getOperand(5));
6290 Inst = TmpInst;
6291 return true;
6292 }
6293
Jim Grosbach086cbfa2012-01-25 00:01:08 +00006294 // VLD4DUP single 3-element structure to all lanes instructions.
6295 case ARM::VLD4DUPdAsm_8:
6296 case ARM::VLD4DUPdAsm_16:
6297 case ARM::VLD4DUPdAsm_32:
6298 case ARM::VLD4DUPqAsm_8:
6299 case ARM::VLD4DUPqAsm_16:
6300 case ARM::VLD4DUPqAsm_32: {
6301 MCInst TmpInst;
6302 unsigned Spacing;
6303 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6304 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6305 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6306 Spacing));
6307 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6308 Spacing * 2));
6309 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6310 Spacing * 3));
6311 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6312 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6313 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6314 TmpInst.addOperand(Inst.getOperand(4));
6315 Inst = TmpInst;
6316 return true;
6317 }
6318
6319 case ARM::VLD4DUPdWB_fixed_Asm_8:
6320 case ARM::VLD4DUPdWB_fixed_Asm_16:
6321 case ARM::VLD4DUPdWB_fixed_Asm_32:
6322 case ARM::VLD4DUPqWB_fixed_Asm_8:
6323 case ARM::VLD4DUPqWB_fixed_Asm_16:
6324 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6325 MCInst TmpInst;
6326 unsigned Spacing;
6327 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6328 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6329 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6330 Spacing));
6331 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6332 Spacing * 2));
6333 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6334 Spacing * 3));
6335 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6336 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6337 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6338 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6339 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6340 TmpInst.addOperand(Inst.getOperand(4));
6341 Inst = TmpInst;
6342 return true;
6343 }
6344
6345 case ARM::VLD4DUPdWB_register_Asm_8:
6346 case ARM::VLD4DUPdWB_register_Asm_16:
6347 case ARM::VLD4DUPdWB_register_Asm_32:
6348 case ARM::VLD4DUPqWB_register_Asm_8:
6349 case ARM::VLD4DUPqWB_register_Asm_16:
6350 case ARM::VLD4DUPqWB_register_Asm_32: {
6351 MCInst TmpInst;
6352 unsigned Spacing;
6353 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6354 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6355 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6356 Spacing));
6357 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6358 Spacing * 2));
6359 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6360 Spacing * 3));
6361 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6362 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6363 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6364 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6365 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6366 TmpInst.addOperand(Inst.getOperand(5));
6367 Inst = TmpInst;
6368 return true;
6369 }
6370
6371 // VLD4 multiple 4-element structure instructions.
Jim Grosbached561fc2012-01-24 00:43:17 +00006372 case ARM::VLD4dAsm_8:
6373 case ARM::VLD4dAsm_16:
6374 case ARM::VLD4dAsm_32:
6375 case ARM::VLD4qAsm_8:
6376 case ARM::VLD4qAsm_16:
6377 case ARM::VLD4qAsm_32: {
6378 MCInst TmpInst;
6379 unsigned Spacing;
6380 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6381 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6382 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6383 Spacing));
6384 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6385 Spacing * 2));
6386 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6387 Spacing * 3));
6388 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6389 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6390 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6391 TmpInst.addOperand(Inst.getOperand(4));
6392 Inst = TmpInst;
6393 return true;
6394 }
6395
6396 case ARM::VLD4dWB_fixed_Asm_8:
6397 case ARM::VLD4dWB_fixed_Asm_16:
6398 case ARM::VLD4dWB_fixed_Asm_32:
6399 case ARM::VLD4qWB_fixed_Asm_8:
6400 case ARM::VLD4qWB_fixed_Asm_16:
6401 case ARM::VLD4qWB_fixed_Asm_32: {
6402 MCInst TmpInst;
6403 unsigned Spacing;
6404 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6405 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6406 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6407 Spacing));
6408 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6409 Spacing * 2));
6410 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6411 Spacing * 3));
6412 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6413 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6414 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6415 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6416 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6417 TmpInst.addOperand(Inst.getOperand(4));
6418 Inst = TmpInst;
6419 return true;
6420 }
6421
6422 case ARM::VLD4dWB_register_Asm_8:
6423 case ARM::VLD4dWB_register_Asm_16:
6424 case ARM::VLD4dWB_register_Asm_32:
6425 case ARM::VLD4qWB_register_Asm_8:
6426 case ARM::VLD4qWB_register_Asm_16:
6427 case ARM::VLD4qWB_register_Asm_32: {
6428 MCInst TmpInst;
6429 unsigned Spacing;
6430 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6431 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6432 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6433 Spacing));
6434 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6435 Spacing * 2));
6436 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6437 Spacing * 3));
6438 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6439 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6440 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6441 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6442 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6443 TmpInst.addOperand(Inst.getOperand(5));
6444 Inst = TmpInst;
6445 return true;
6446 }
6447
Jim Grosbach1a747242012-01-23 23:45:44 +00006448 // VST3 multiple 3-element structure instructions.
6449 case ARM::VST3dAsm_8:
6450 case ARM::VST3dAsm_16:
6451 case ARM::VST3dAsm_32:
6452 case ARM::VST3qAsm_8:
6453 case ARM::VST3qAsm_16:
6454 case ARM::VST3qAsm_32: {
6455 MCInst TmpInst;
6456 unsigned Spacing;
6457 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6458 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6459 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6460 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6461 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6462 Spacing));
6463 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6464 Spacing * 2));
6465 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6466 TmpInst.addOperand(Inst.getOperand(4));
6467 Inst = TmpInst;
6468 return true;
6469 }
6470
6471 case ARM::VST3dWB_fixed_Asm_8:
6472 case ARM::VST3dWB_fixed_Asm_16:
6473 case ARM::VST3dWB_fixed_Asm_32:
6474 case ARM::VST3qWB_fixed_Asm_8:
6475 case ARM::VST3qWB_fixed_Asm_16:
6476 case ARM::VST3qWB_fixed_Asm_32: {
6477 MCInst TmpInst;
6478 unsigned Spacing;
6479 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6480 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6481 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6482 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6483 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6484 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6485 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6486 Spacing));
6487 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6488 Spacing * 2));
6489 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6490 TmpInst.addOperand(Inst.getOperand(4));
6491 Inst = TmpInst;
6492 return true;
6493 }
6494
6495 case ARM::VST3dWB_register_Asm_8:
6496 case ARM::VST3dWB_register_Asm_16:
6497 case ARM::VST3dWB_register_Asm_32:
6498 case ARM::VST3qWB_register_Asm_8:
6499 case ARM::VST3qWB_register_Asm_16:
6500 case ARM::VST3qWB_register_Asm_32: {
6501 MCInst TmpInst;
6502 unsigned Spacing;
6503 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6504 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6505 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6506 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6507 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6508 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6509 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6510 Spacing));
6511 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6512 Spacing * 2));
6513 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6514 TmpInst.addOperand(Inst.getOperand(5));
6515 Inst = TmpInst;
6516 return true;
6517 }
6518
Jim Grosbachda70eac2012-01-24 00:58:13 +00006519 // VST4 multiple 3-element structure instructions.
6520 case ARM::VST4dAsm_8:
6521 case ARM::VST4dAsm_16:
6522 case ARM::VST4dAsm_32:
6523 case ARM::VST4qAsm_8:
6524 case ARM::VST4qAsm_16:
6525 case ARM::VST4qAsm_32: {
6526 MCInst TmpInst;
6527 unsigned Spacing;
6528 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6529 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6530 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6531 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6532 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6533 Spacing));
6534 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6535 Spacing * 2));
6536 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6537 Spacing * 3));
6538 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6539 TmpInst.addOperand(Inst.getOperand(4));
6540 Inst = TmpInst;
6541 return true;
6542 }
6543
6544 case ARM::VST4dWB_fixed_Asm_8:
6545 case ARM::VST4dWB_fixed_Asm_16:
6546 case ARM::VST4dWB_fixed_Asm_32:
6547 case ARM::VST4qWB_fixed_Asm_8:
6548 case ARM::VST4qWB_fixed_Asm_16:
6549 case ARM::VST4qWB_fixed_Asm_32: {
6550 MCInst TmpInst;
6551 unsigned Spacing;
6552 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6553 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6554 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6555 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6556 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6557 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6558 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6559 Spacing));
6560 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6561 Spacing * 2));
6562 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6563 Spacing * 3));
6564 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6565 TmpInst.addOperand(Inst.getOperand(4));
6566 Inst = TmpInst;
6567 return true;
6568 }
6569
6570 case ARM::VST4dWB_register_Asm_8:
6571 case ARM::VST4dWB_register_Asm_16:
6572 case ARM::VST4dWB_register_Asm_32:
6573 case ARM::VST4qWB_register_Asm_8:
6574 case ARM::VST4qWB_register_Asm_16:
6575 case ARM::VST4qWB_register_Asm_32: {
6576 MCInst TmpInst;
6577 unsigned Spacing;
6578 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6579 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6580 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6581 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6582 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6583 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6584 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6585 Spacing));
6586 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6587 Spacing * 2));
6588 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6589 Spacing * 3));
6590 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6591 TmpInst.addOperand(Inst.getOperand(5));
6592 Inst = TmpInst;
6593 return true;
6594 }
6595
Jim Grosbach485e5622011-12-13 22:45:11 +00006596 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbachb3ef7132011-12-21 20:54:00 +00006597 case ARM::t2MOVsr:
6598 case ARM::t2MOVSsr: {
6599 // Which instruction to expand to depends on the CCOut operand and
6600 // whether we're in an IT block if the register operands are low
6601 // registers.
6602 bool isNarrow = false;
6603 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6604 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6605 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6606 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6607 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6608 isNarrow = true;
6609 MCInst TmpInst;
6610 unsigned newOpc;
6611 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6612 default: llvm_unreachable("unexpected opcode!");
6613 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6614 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6615 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6616 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6617 }
6618 TmpInst.setOpcode(newOpc);
6619 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6620 if (isNarrow)
6621 TmpInst.addOperand(MCOperand::CreateReg(
6622 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6623 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6624 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6625 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6626 TmpInst.addOperand(Inst.getOperand(5));
6627 if (!isNarrow)
6628 TmpInst.addOperand(MCOperand::CreateReg(
6629 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6630 Inst = TmpInst;
6631 return true;
6632 }
Jim Grosbach485e5622011-12-13 22:45:11 +00006633 case ARM::t2MOVsi:
6634 case ARM::t2MOVSsi: {
6635 // Which instruction to expand to depends on the CCOut operand and
6636 // whether we're in an IT block if the register operands are low
6637 // registers.
6638 bool isNarrow = false;
6639 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6640 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6641 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6642 isNarrow = true;
6643 MCInst TmpInst;
6644 unsigned newOpc;
6645 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6646 default: llvm_unreachable("unexpected opcode!");
6647 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6648 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6649 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6650 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00006651 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach485e5622011-12-13 22:45:11 +00006652 }
6653 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6654 if (Ammount == 32) Ammount = 0;
6655 TmpInst.setOpcode(newOpc);
6656 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6657 if (isNarrow)
6658 TmpInst.addOperand(MCOperand::CreateReg(
6659 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6660 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00006661 if (newOpc != ARM::t2RRX)
6662 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach485e5622011-12-13 22:45:11 +00006663 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6664 TmpInst.addOperand(Inst.getOperand(4));
6665 if (!isNarrow)
6666 TmpInst.addOperand(MCOperand::CreateReg(
6667 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6668 Inst = TmpInst;
6669 return true;
6670 }
6671 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00006672 case ARM::ASRr:
6673 case ARM::LSRr:
6674 case ARM::LSLr:
6675 case ARM::RORr: {
6676 ARM_AM::ShiftOpc ShiftTy;
6677 switch(Inst.getOpcode()) {
6678 default: llvm_unreachable("unexpected opcode!");
6679 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6680 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6681 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6682 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6683 }
Jim Grosbachabcac562011-11-16 18:31:45 +00006684 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6685 MCInst TmpInst;
6686 TmpInst.setOpcode(ARM::MOVsr);
6687 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6688 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6689 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6690 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6691 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6692 TmpInst.addOperand(Inst.getOperand(4));
6693 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6694 Inst = TmpInst;
6695 return true;
6696 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00006697 case ARM::ASRi:
6698 case ARM::LSRi:
6699 case ARM::LSLi:
6700 case ARM::RORi: {
6701 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00006702 switch(Inst.getOpcode()) {
6703 default: llvm_unreachable("unexpected opcode!");
6704 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6705 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6706 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6707 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6708 }
6709 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00006710 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00006711 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6712 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00006713 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00006714 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00006715 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6716 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00006717 if (Opc == ARM::MOVsi)
6718 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00006719 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6720 TmpInst.addOperand(Inst.getOperand(4));
6721 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6722 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006723 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00006724 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00006725 case ARM::RRXi: {
6726 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6727 MCInst TmpInst;
6728 TmpInst.setOpcode(ARM::MOVsi);
6729 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6730 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6731 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6732 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6733 TmpInst.addOperand(Inst.getOperand(3));
6734 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6735 Inst = TmpInst;
6736 return true;
6737 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00006738 case ARM::t2LDMIA_UPD: {
6739 // If this is a load of a single register, then we should use
6740 // a post-indexed LDR instruction instead, per the ARM ARM.
6741 if (Inst.getNumOperands() != 5)
6742 return false;
6743 MCInst TmpInst;
6744 TmpInst.setOpcode(ARM::t2LDR_POST);
6745 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6746 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6747 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6748 TmpInst.addOperand(MCOperand::CreateImm(4));
6749 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6750 TmpInst.addOperand(Inst.getOperand(3));
6751 Inst = TmpInst;
6752 return true;
6753 }
6754 case ARM::t2STMDB_UPD: {
6755 // If this is a store of a single register, then we should use
6756 // a pre-indexed STR instruction instead, per the ARM ARM.
6757 if (Inst.getNumOperands() != 5)
6758 return false;
6759 MCInst TmpInst;
6760 TmpInst.setOpcode(ARM::t2STR_PRE);
6761 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6762 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6763 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6764 TmpInst.addOperand(MCOperand::CreateImm(-4));
6765 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6766 TmpInst.addOperand(Inst.getOperand(3));
6767 Inst = TmpInst;
6768 return true;
6769 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006770 case ARM::LDMIA_UPD:
6771 // If this is a load of a single register via a 'pop', then we should use
6772 // a post-indexed LDR instruction instead, per the ARM ARM.
6773 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6774 Inst.getNumOperands() == 5) {
6775 MCInst TmpInst;
6776 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6777 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6778 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6779 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6780 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6781 TmpInst.addOperand(MCOperand::CreateImm(4));
6782 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6783 TmpInst.addOperand(Inst.getOperand(3));
6784 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006785 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006786 }
6787 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00006788 case ARM::STMDB_UPD:
6789 // If this is a store of a single register via a 'push', then we should use
6790 // a pre-indexed STR instruction instead, per the ARM ARM.
6791 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6792 Inst.getNumOperands() == 5) {
6793 MCInst TmpInst;
6794 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6795 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6796 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6797 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6798 TmpInst.addOperand(MCOperand::CreateImm(-4));
6799 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6800 TmpInst.addOperand(Inst.getOperand(3));
6801 Inst = TmpInst;
6802 }
6803 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00006804 case ARM::t2ADDri12:
6805 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6806 // mnemonic was used (not "addw"), encoding T3 is preferred.
6807 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6808 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6809 break;
6810 Inst.setOpcode(ARM::t2ADDri);
6811 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6812 break;
6813 case ARM::t2SUBri12:
6814 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6815 // mnemonic was used (not "subw"), encoding T3 is preferred.
6816 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6817 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6818 break;
6819 Inst.setOpcode(ARM::t2SUBri);
6820 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6821 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006822 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00006823 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6824 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6825 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6826 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00006827 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006828 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006829 return true;
6830 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00006831 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006832 case ARM::tSUBi8:
6833 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6834 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6835 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6836 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00006837 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006838 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006839 return true;
6840 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006841 break;
Jim Grosbache489bab2011-12-05 22:16:39 +00006842 case ARM::t2ADDrr: {
6843 // If the destination and first source operand are the same, and
6844 // there's no setting of the flags, use encoding T2 instead of T3.
6845 // Note that this is only for ADD, not SUB. This mirrors the system
6846 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6847 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6848 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00006849 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6850 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00006851 break;
6852 MCInst TmpInst;
6853 TmpInst.setOpcode(ARM::tADDhirr);
6854 TmpInst.addOperand(Inst.getOperand(0));
6855 TmpInst.addOperand(Inst.getOperand(0));
6856 TmpInst.addOperand(Inst.getOperand(2));
6857 TmpInst.addOperand(Inst.getOperand(3));
6858 TmpInst.addOperand(Inst.getOperand(4));
6859 Inst = TmpInst;
6860 return true;
6861 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006862 case ARM::tB:
6863 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006864 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006865 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006866 return true;
6867 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006868 break;
6869 case ARM::t2B:
6870 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006871 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006872 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006873 return true;
6874 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006875 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00006876 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006877 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00006878 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00006879 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00006880 return true;
6881 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00006882 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006883 case ARM::tBcc:
6884 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00006885 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006886 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00006887 return true;
6888 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00006889 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006890 case ARM::tLDMIA: {
6891 // If the register list contains any high registers, or if the writeback
6892 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6893 // instead if we're in Thumb2. Otherwise, this should have generated
6894 // an error in validateInstruction().
6895 unsigned Rn = Inst.getOperand(0).getReg();
6896 bool hasWritebackToken =
6897 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6898 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6899 bool listContainsBase;
6900 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6901 (!listContainsBase && !hasWritebackToken) ||
6902 (listContainsBase && hasWritebackToken)) {
6903 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6904 assert (isThumbTwo());
6905 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6906 // If we're switching to the updating version, we need to insert
6907 // the writeback tied operand.
6908 if (hasWritebackToken)
6909 Inst.insert(Inst.begin(),
6910 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00006911 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006912 }
6913 break;
6914 }
Jim Grosbach099c9762011-09-16 20:50:13 +00006915 case ARM::tSTMIA_UPD: {
6916 // If the register list contains any high registers, we need to use
6917 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6918 // should have generated an error in validateInstruction().
6919 unsigned Rn = Inst.getOperand(0).getReg();
6920 bool listContainsBase;
6921 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6922 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6923 assert (isThumbTwo());
6924 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00006925 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00006926 }
6927 break;
6928 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006929 case ARM::tPOP: {
6930 bool listContainsBase;
6931 // If the register list contains any high registers, we need to use
6932 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6933 // should have generated an error in validateInstruction().
6934 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006935 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006936 assert (isThumbTwo());
6937 Inst.setOpcode(ARM::t2LDMIA_UPD);
6938 // Add the base register and writeback operands.
6939 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6940 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006941 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006942 }
6943 case ARM::tPUSH: {
6944 bool listContainsBase;
6945 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006946 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006947 assert (isThumbTwo());
6948 Inst.setOpcode(ARM::t2STMDB_UPD);
6949 // Add the base register and writeback operands.
6950 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6951 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006952 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006953 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006954 case ARM::t2MOVi: {
6955 // If we can use the 16-bit encoding and the user didn't explicitly
6956 // request the 32-bit variant, transform it here.
6957 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6958 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00006959 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6960 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6961 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006962 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6963 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6964 // The operands aren't in the same order for tMOVi8...
6965 MCInst TmpInst;
6966 TmpInst.setOpcode(ARM::tMOVi8);
6967 TmpInst.addOperand(Inst.getOperand(0));
6968 TmpInst.addOperand(Inst.getOperand(4));
6969 TmpInst.addOperand(Inst.getOperand(1));
6970 TmpInst.addOperand(Inst.getOperand(2));
6971 TmpInst.addOperand(Inst.getOperand(3));
6972 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006973 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006974 }
6975 break;
6976 }
6977 case ARM::t2MOVr: {
6978 // If we can use the 16-bit encoding and the user didn't explicitly
6979 // request the 32-bit variant, transform it here.
6980 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6981 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6982 Inst.getOperand(2).getImm() == ARMCC::AL &&
6983 Inst.getOperand(4).getReg() == ARM::CPSR &&
6984 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6985 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6986 // The operands aren't the same for tMOV[S]r... (no cc_out)
6987 MCInst TmpInst;
6988 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6989 TmpInst.addOperand(Inst.getOperand(0));
6990 TmpInst.addOperand(Inst.getOperand(1));
6991 TmpInst.addOperand(Inst.getOperand(2));
6992 TmpInst.addOperand(Inst.getOperand(3));
6993 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006994 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006995 }
6996 break;
6997 }
Jim Grosbach82213192011-09-19 20:29:33 +00006998 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00006999 case ARM::t2SXTB:
7000 case ARM::t2UXTH:
7001 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00007002 // If we can use the 16-bit encoding and the user didn't explicitly
7003 // request the 32-bit variant, transform it here.
7004 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7005 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7006 Inst.getOperand(2).getImm() == 0 &&
7007 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7008 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00007009 unsigned NewOpc;
7010 switch (Inst.getOpcode()) {
7011 default: llvm_unreachable("Illegal opcode!");
7012 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7013 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7014 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7015 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7016 }
Jim Grosbach82213192011-09-19 20:29:33 +00007017 // The operands aren't the same for thumb1 (no rotate operand).
7018 MCInst TmpInst;
7019 TmpInst.setOpcode(NewOpc);
7020 TmpInst.addOperand(Inst.getOperand(0));
7021 TmpInst.addOperand(Inst.getOperand(1));
7022 TmpInst.addOperand(Inst.getOperand(3));
7023 TmpInst.addOperand(Inst.getOperand(4));
7024 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007025 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00007026 }
7027 break;
7028 }
Jim Grosbache2ca9e52011-12-20 00:59:38 +00007029 case ARM::MOVsi: {
7030 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7031 if (SOpc == ARM_AM::rrx) return false;
7032 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7033 // Shifting by zero is accepted as a vanilla 'MOVr'
7034 MCInst TmpInst;
7035 TmpInst.setOpcode(ARM::MOVr);
7036 TmpInst.addOperand(Inst.getOperand(0));
7037 TmpInst.addOperand(Inst.getOperand(1));
7038 TmpInst.addOperand(Inst.getOperand(3));
7039 TmpInst.addOperand(Inst.getOperand(4));
7040 TmpInst.addOperand(Inst.getOperand(5));
7041 Inst = TmpInst;
7042 return true;
7043 }
7044 return false;
7045 }
Jim Grosbach12ccf452011-12-22 18:04:04 +00007046 case ARM::ANDrsi:
7047 case ARM::ORRrsi:
7048 case ARM::EORrsi:
7049 case ARM::BICrsi:
7050 case ARM::SUBrsi:
7051 case ARM::ADDrsi: {
7052 unsigned newOpc;
7053 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7054 if (SOpc == ARM_AM::rrx) return false;
7055 switch (Inst.getOpcode()) {
Craig Toppere55c5562012-02-07 02:50:20 +00007056 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach12ccf452011-12-22 18:04:04 +00007057 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7058 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7059 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7060 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7061 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7062 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7063 }
7064 // If the shift is by zero, use the non-shifted instruction definition.
7065 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7066 MCInst TmpInst;
7067 TmpInst.setOpcode(newOpc);
7068 TmpInst.addOperand(Inst.getOperand(0));
7069 TmpInst.addOperand(Inst.getOperand(1));
7070 TmpInst.addOperand(Inst.getOperand(2));
7071 TmpInst.addOperand(Inst.getOperand(4));
7072 TmpInst.addOperand(Inst.getOperand(5));
7073 TmpInst.addOperand(Inst.getOperand(6));
7074 Inst = TmpInst;
7075 return true;
7076 }
7077 return false;
7078 }
Jim Grosbach82f76d12012-01-25 19:52:01 +00007079 case ARM::ITasm:
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007080 case ARM::t2IT: {
7081 // The mask bits for all but the first condition are represented as
7082 // the low bit of the condition code value implies 't'. We currently
7083 // always have 1 implies 't', so XOR toggle the bits if the low bit
7084 // of the condition code is zero. The encoding also expects the low
7085 // bit of the condition to be encoded as bit 4 of the mask operand,
7086 // so mask that in if needed
7087 MCOperand &MO = Inst.getOperand(1);
7088 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00007089 unsigned OrigMask = Mask;
7090 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007091 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007092 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7093 for (unsigned i = 3; i != TZ; --i)
7094 Mask ^= 1 << i;
7095 } else
7096 Mask |= 0x10;
7097 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00007098
7099 // Set up the IT block state according to the IT instruction we just
7100 // matched.
7101 assert(!inITBlock() && "nested IT blocks?!");
7102 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7103 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7104 ITState.CurPosition = 0;
7105 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00007106 break;
7107 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007108 }
Jim Grosbachafad0532011-11-10 23:42:14 +00007109 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007110}
7111
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007112unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7113 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7114 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007115 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00007116 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007117 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7118 assert(MCID.hasOptionalDef() &&
7119 "optionally flag setting instruction missing optional def operand");
7120 assert(MCID.NumOperands == Inst.getNumOperands() &&
7121 "operand count mismatch!");
7122 // Find the optional-def operand (cc_out).
7123 unsigned OpNo;
7124 for (OpNo = 0;
7125 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7126 ++OpNo)
7127 ;
7128 // If we're parsing Thumb1, reject it completely.
7129 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7130 return Match_MnemonicFail;
7131 // If we're parsing Thumb2, which form is legal depends on whether we're
7132 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00007133 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7134 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007135 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00007136 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7137 inITBlock())
7138 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007139 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007140 // Some high-register supporting Thumb1 encodings only allow both registers
7141 // to be from r0-r7 when in Thumb2.
7142 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7143 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7144 isARMLowRegister(Inst.getOperand(2).getReg()))
7145 return Match_RequiresThumb2;
7146 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00007147 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007148 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7149 isARMLowRegister(Inst.getOperand(1).getReg()))
7150 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007151 return Match_Success;
7152}
7153
Chris Lattner9487de62010-10-28 21:28:01 +00007154bool ARMAsmParser::
7155MatchAndEmitInstruction(SMLoc IDLoc,
7156 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7157 MCStreamer &Out) {
7158 MCInst Inst;
7159 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00007160 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00007161 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00007162 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00007163 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007164 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007165 // Context sensitive operand constraints aren't handled by the matcher,
7166 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007167 if (validateInstruction(Inst, Operands)) {
7168 // Still progress the IT block, otherwise one wrong condition causes
7169 // nasty cascading errors.
7170 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007171 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007172 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00007173
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007174 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00007175 // encoding is selected. Loop on it while changes happen so the
7176 // individual transformations can chain off each other. E.g.,
7177 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7178 while (processInstruction(Inst, Operands))
7179 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007180
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007181 // Only move forward at the very end so that everything in validate
7182 // and process gets a consistent answer about whether we're in an IT
7183 // block.
7184 forwardITPosition();
7185
Jim Grosbach82f76d12012-01-25 19:52:01 +00007186 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7187 // doesn't actually encode.
7188 if (Inst.getOpcode() == ARM::ITasm)
7189 return false;
7190
Jim Grosbach5e5eabb2012-01-26 23:20:15 +00007191 Inst.setLoc(IDLoc);
Chris Lattner9487de62010-10-28 21:28:01 +00007192 Out.EmitInstruction(Inst);
7193 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007194 case Match_MissingFeature:
7195 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7196 return true;
7197 case Match_InvalidOperand: {
7198 SMLoc ErrorLoc = IDLoc;
7199 if (ErrorInfo != ~0U) {
7200 if (ErrorInfo >= Operands.size())
7201 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00007202
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007203 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7204 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7205 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00007206
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007207 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00007208 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007209 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007210 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00007211 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00007212 // The converter function will have already emited a diagnostic.
7213 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00007214 case Match_RequiresNotITBlock:
7215 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00007216 case Match_RequiresITBlock:
7217 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00007218 case Match_RequiresV6:
7219 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7220 case Match_RequiresThumb2:
7221 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00007222 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00007223
Eric Christopher91d7b902010-10-29 09:26:59 +00007224 llvm_unreachable("Implement any new match types added!");
Chris Lattner9487de62010-10-28 21:28:01 +00007225}
7226
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007227/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00007228bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7229 StringRef IDVal = DirectiveID.getIdentifier();
7230 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007231 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007232 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007233 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00007234 else if (IDVal == ".arm")
7235 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007236 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007237 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007238 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007239 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00007240 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007241 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00007242 else if (IDVal == ".unreq")
7243 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kim135d2442011-12-20 17:38:12 +00007244 else if (IDVal == ".arch")
7245 return parseDirectiveArch(DirectiveID.getLoc());
7246 else if (IDVal == ".eabi_attribute")
7247 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00007248 return true;
7249}
7250
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007251/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00007252/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007253bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00007254 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7255 for (;;) {
7256 const MCExpr *Value;
7257 if (getParser().ParseExpression(Value))
7258 return true;
7259
Chris Lattnerc35681b2010-01-19 19:46:13 +00007260 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00007261
7262 if (getLexer().is(AsmToken::EndOfStatement))
7263 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00007264
Kevin Enderbyccab3172009-09-15 00:27:25 +00007265 // FIXME: Improve diagnostic.
7266 if (getLexer().isNot(AsmToken::Comma))
7267 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007268 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007269 }
7270 }
7271
Sean Callanana83fd7d2010-01-19 20:27:46 +00007272 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007273 return false;
7274}
7275
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007276/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00007277/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007278bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00007279 if (getLexer().isNot(AsmToken::EndOfStatement))
7280 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007281 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007282
Jim Grosbach7f882392011-12-07 18:04:19 +00007283 if (!isThumb())
7284 SwitchMode();
7285 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7286 return false;
7287}
7288
7289/// parseDirectiveARM
7290/// ::= .arm
7291bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7292 if (getLexer().isNot(AsmToken::EndOfStatement))
7293 return Error(L, "unexpected token in directive");
7294 Parser.Lex();
7295
7296 if (isThumb())
7297 SwitchMode();
7298 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00007299 return false;
7300}
7301
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007302/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00007303/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007304bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007305 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7306 bool isMachO = MAI.hasSubsectionsViaSymbols();
7307 StringRef Name;
Jim Grosbach1152cc02011-12-21 22:30:16 +00007308 bool needFuncName = true;
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007309
Jim Grosbach1152cc02011-12-21 22:30:16 +00007310 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007311 // ELF doesn't
7312 if (isMachO) {
7313 const AsmToken &Tok = Parser.getTok();
Jim Grosbach1152cc02011-12-21 22:30:16 +00007314 if (Tok.isNot(AsmToken::EndOfStatement)) {
7315 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7316 return Error(L, "unexpected token in .thumb_func directive");
7317 Name = Tok.getIdentifier();
7318 Parser.Lex(); // Consume the identifier token.
7319 needFuncName = false;
7320 }
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007321 }
7322
Jim Grosbach1152cc02011-12-21 22:30:16 +00007323 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00007324 return Error(L, "unexpected token in directive");
Jim Grosbach1152cc02011-12-21 22:30:16 +00007325
7326 // Eat the end of statement and any blank lines that follow.
7327 while (getLexer().is(AsmToken::EndOfStatement))
7328 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007329
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007330 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbach1152cc02011-12-21 22:30:16 +00007331 // We really should be checking the next symbol definition even if there's
7332 // stuff in between.
7333 if (needFuncName) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00007334 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00007335 }
7336
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00007337 // Mark symbol as a thumb symbol.
7338 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7339 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00007340 return false;
7341}
7342
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007343/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00007344/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007345bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00007346 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007347 if (Tok.isNot(AsmToken::Identifier))
7348 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00007349 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00007350 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00007351 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00007352 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00007353 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00007354 else
7355 return Error(L, "unrecognized syntax mode in .syntax directive");
7356
7357 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00007358 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007359 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007360
7361 // TODO tell the MC streamer the mode
7362 // getParser().getStreamer().Emit???();
7363 return false;
7364}
7365
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007366/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00007367/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00007368bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00007369 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007370 if (Tok.isNot(AsmToken::Integer))
7371 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00007372 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00007373 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00007374 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00007375 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00007376 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007377 else
7378 return Error(L, "invalid operand to .code directive");
7379
7380 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00007381 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00007382 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00007383
Evan Cheng284b4672011-07-08 22:36:29 +00007384 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00007385 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00007386 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00007387 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00007388 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00007389 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00007390 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00007391 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00007392 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00007393
Kevin Enderby146dcf22009-10-15 20:48:48 +00007394 return false;
7395}
7396
Jim Grosbachab5830e2011-12-14 02:16:11 +00007397/// parseDirectiveReq
7398/// ::= name .req registername
7399bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7400 Parser.Lex(); // Eat the '.req' token.
7401 unsigned Reg;
7402 SMLoc SRegLoc, ERegLoc;
7403 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7404 Parser.EatToEndOfStatement();
7405 return Error(SRegLoc, "register name expected");
7406 }
7407
7408 // Shouldn't be anything else.
7409 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7410 Parser.EatToEndOfStatement();
7411 return Error(Parser.getTok().getLoc(),
7412 "unexpected input in .req directive.");
7413 }
7414
7415 Parser.Lex(); // Consume the EndOfStatement
7416
7417 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7418 return Error(SRegLoc, "redefinition of '" + Name +
7419 "' does not match original.");
7420
7421 return false;
7422}
7423
7424/// parseDirectiveUneq
7425/// ::= .unreq registername
7426bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7427 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7428 Parser.EatToEndOfStatement();
7429 return Error(L, "unexpected input in .unreq directive.");
7430 }
7431 RegisterReqs.erase(Parser.getTok().getIdentifier());
7432 Parser.Lex(); // Eat the identifier.
7433 return false;
7434}
7435
Jason W Kim135d2442011-12-20 17:38:12 +00007436/// parseDirectiveArch
7437/// ::= .arch token
7438bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7439 return true;
7440}
7441
7442/// parseDirectiveEabiAttr
7443/// ::= .eabi_attribute int, int
7444bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7445 return true;
7446}
7447
Sean Callanan643a5572010-04-07 20:29:34 +00007448extern "C" void LLVMInitializeARMAsmLexer();
7449
Kevin Enderby8be42bd2009-10-30 22:55:57 +00007450/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00007451extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00007452 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7453 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00007454 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00007455}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00007456
Chris Lattner3e4582a2010-09-06 19:11:01 +00007457#define GET_REGISTER_MATCHER
7458#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00007459#include "ARMGenAsmMatcher.inc"