blob: 83e7aac2fbfe1f2dc341264cf2acfd348bca6789 [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
Evan Cheng11424442011-07-26 00:24:13 +000042class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +000043 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000044 MCAsmParser &Parser;
45
Jim Grosbached16ec42011-08-29 22:24:09 +000046 struct {
47 ARMCC::CondCodes Cond; // Condition for IT block.
48 unsigned Mask:4; // Condition mask for instructions.
49 // Starting at first 1 (from lsb).
50 // '1' condition as indicated in IT.
51 // '0' inverse of condition (else).
52 // Count of instructions in IT block is
53 // 4 - trailingzeroes(mask)
54
55 bool FirstCond; // Explicit flag for when we're parsing the
56 // First instruction in the IT block. It's
57 // implied in the mask, so needs special
58 // handling.
59
60 unsigned CurPosition; // Current position in parsing of IT
61 // block. In range [0,3]. Initialized
62 // according to count of instructions in block.
63 // ~0U if no active IT block.
64 } ITState;
65 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000066 void forwardITPosition() {
67 if (!inITBlock()) return;
68 // Move to the next instruction in the IT block, if there is one. If not,
69 // mark the block as done.
70 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
71 if (++ITState.CurPosition == 5 - TZ)
72 ITState.CurPosition = ~0U; // Done with the IT block after this.
73 }
Jim Grosbached16ec42011-08-29 22:24:09 +000074
75
Kevin Enderbyccab3172009-09-15 00:27:25 +000076 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000077 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
78
79 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000080 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
81
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000082 int tryParseRegister();
83 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000084 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000085 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000086 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000087 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
88 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000089 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
90 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000091 bool parseDirectiveWord(unsigned Size, SMLoc L);
92 bool parseDirectiveThumb(SMLoc L);
93 bool parseDirectiveThumbFunc(SMLoc L);
94 bool parseDirectiveCode(SMLoc L);
95 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +000096
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000097 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +000098 bool &CarrySetting, unsigned &ProcessorIMod,
99 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000100 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000101 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000102
Evan Cheng4d1ca962011-07-08 01:53:10 +0000103 bool isThumb() const {
104 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000105 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000106 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000107 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000108 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000109 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000110 bool isThumbTwo() const {
111 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
112 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000113 bool hasV6Ops() const {
114 return STI.getFeatureBits() & ARM::HasV6Ops;
115 }
James Molloy21efa7d2011-09-28 14:21:38 +0000116 bool hasV7Ops() const {
117 return STI.getFeatureBits() & ARM::HasV7Ops;
118 }
Evan Cheng284b4672011-07-08 22:36:29 +0000119 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000120 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
121 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000122 }
James Molloy21efa7d2011-09-28 14:21:38 +0000123 bool isMClass() const {
124 return STI.getFeatureBits() & ARM::FeatureMClass;
125 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000126
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000127 /// @name Auto-generated Match Functions
128 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000129
Chris Lattner3e4582a2010-09-06 19:11:01 +0000130#define GET_ASSEMBLER_HEADER
131#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000132
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000133 /// }
134
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000135 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000136 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000137 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000138 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000139 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000140 OperandMatchResultTy parseCoprocOptionOperand(
141 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000142 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000143 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000144 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000146 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000148 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
149 StringRef Op, int Low, int High);
150 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
151 return parsePKHImm(O, "lsl", 0, 31);
152 }
153 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
154 return parsePKHImm(O, "asr", 1, 32);
155 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000156 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000157 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000158 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000159 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000160 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000161 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000162 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000163 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000164
165 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000166 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
168 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000170 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000172 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000174 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000176 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000178 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000180 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000182 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000184 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000192 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000194 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000196 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000198 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach3ea06572011-10-24 22:16:58 +0000200 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
202 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach05df4602011-10-31 21:50:31 +0000204 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000208
209 bool validateInstruction(MCInst &Inst,
210 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000211 void processInstruction(MCInst &Inst,
212 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000213 bool shouldOmitCCOutOperand(StringRef Mnemonic,
214 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000215
Kevin Enderbyccab3172009-09-15 00:27:25 +0000216public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000217 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000218 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000219 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000220 Match_RequiresV6,
221 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000222 };
223
Evan Cheng91111d22011-07-09 05:47:46 +0000224 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000225 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000226 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000227
Evan Cheng4d1ca962011-07-08 01:53:10 +0000228 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000229 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000230
231 // Not in an ITBlock to start with.
232 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000233 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000234
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000235 // Implementation of the MCTargetAsmParser interface:
236 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
237 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000238 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000239 bool ParseDirective(AsmToken DirectiveID);
240
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000241 unsigned checkTargetMatchPredicate(MCInst &Inst);
242
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000243 bool MatchAndEmitInstruction(SMLoc IDLoc,
244 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
245 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000246};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000247} // end anonymous namespace
248
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000249namespace {
250
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000251/// ARMOperand - Instances of this class represent a parsed ARM machine
252/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000253class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000254 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000255 k_CondCode,
256 k_CCOut,
257 k_ITCondMask,
258 k_CoprocNum,
259 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000260 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000261 k_Immediate,
262 k_FPImmediate,
263 k_MemBarrierOpt,
264 k_Memory,
265 k_PostIndexRegister,
266 k_MSRMask,
267 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000268 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000269 k_Register,
270 k_RegisterList,
271 k_DPRRegisterList,
272 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000273 k_VectorList,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000274 k_ShiftedRegister,
275 k_ShiftedImmediate,
276 k_ShifterImmediate,
277 k_RotateImmediate,
278 k_BitfieldDescriptor,
279 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000280 } Kind;
281
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000282 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000283 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000284
285 union {
286 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000287 ARMCC::CondCodes Val;
288 } CC;
289
290 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000291 unsigned Val;
292 } Cop;
293
294 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000295 unsigned Val;
296 } CoprocOption;
297
298 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000299 unsigned Mask:4;
300 } ITMask;
301
302 struct {
303 ARM_MB::MemBOpt Val;
304 } MBOpt;
305
306 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000307 ARM_PROC::IFlags Val;
308 } IFlags;
309
310 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000311 unsigned Val;
312 } MMask;
313
314 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000315 const char *Data;
316 unsigned Length;
317 } Tok;
318
319 struct {
320 unsigned RegNum;
321 } Reg;
322
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000323 // A vector register list is a sequential list of 1 to 4 registers.
324 struct {
325 unsigned RegNum;
326 unsigned Count;
327 } VectorList;
328
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000329 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000330 unsigned Val;
331 } VectorIndex;
332
333 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000334 const MCExpr *Val;
335 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000336
Jim Grosbache7fbce72011-10-03 23:38:36 +0000337 struct {
338 unsigned Val; // encoded 8-bit representation
339 } FPImm;
340
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000341 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000342 struct {
343 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000344 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
345 // was specified.
346 const MCConstantExpr *OffsetImm; // Offset immediate value
347 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
348 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000349 unsigned ShiftImm; // shift for OffsetReg.
350 unsigned Alignment; // 0 = no alignment specified
351 // n = alignment in bytes (8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000352 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000353 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000354
355 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000356 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000357 bool isAdd;
358 ARM_AM::ShiftOpc ShiftTy;
359 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000360 } PostIdxReg;
361
362 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000363 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000364 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000365 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000366 struct {
367 ARM_AM::ShiftOpc ShiftTy;
368 unsigned SrcReg;
369 unsigned ShiftReg;
370 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000371 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000372 struct {
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned SrcReg;
375 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000376 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000377 struct {
378 unsigned Imm;
379 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000380 struct {
381 unsigned LSB;
382 unsigned Width;
383 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000384 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000385
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000386 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
387public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000388 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
389 Kind = o.Kind;
390 StartLoc = o.StartLoc;
391 EndLoc = o.EndLoc;
392 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000393 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000394 CC = o.CC;
395 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000396 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000397 ITMask = o.ITMask;
398 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000399 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000400 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000401 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000402 case k_CCOut:
403 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000404 Reg = o.Reg;
405 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000406 case k_RegisterList:
407 case k_DPRRegisterList:
408 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000409 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000410 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000411 case k_VectorList:
412 VectorList = o.VectorList;
413 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000414 case k_CoprocNum:
415 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000416 Cop = o.Cop;
417 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000418 case k_CoprocOption:
419 CoprocOption = o.CoprocOption;
420 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000421 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000422 Imm = o.Imm;
423 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000424 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000425 FPImm = o.FPImm;
426 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000427 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000428 MBOpt = o.MBOpt;
429 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000430 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000431 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000432 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000433 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000434 PostIdxReg = o.PostIdxReg;
435 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000436 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000437 MMask = o.MMask;
438 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000439 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000440 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000441 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000442 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000443 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000444 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000445 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000446 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000447 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000448 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000449 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000450 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000451 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000452 RotImm = o.RotImm;
453 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000454 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000455 Bitfield = o.Bitfield;
456 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000457 case k_VectorIndex:
458 VectorIndex = o.VectorIndex;
459 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000460 }
461 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000462
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000463 /// getStartLoc - Get the location of the first token of this operand.
464 SMLoc getStartLoc() const { return StartLoc; }
465 /// getEndLoc - Get the location of the last token of this operand.
466 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000467
Daniel Dunbard8042b72010-08-11 06:36:53 +0000468 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000469 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000470 return CC.Val;
471 }
472
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000473 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000474 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000475 return Cop.Val;
476 }
477
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000478 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000479 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000480 return StringRef(Tok.Data, Tok.Length);
481 }
482
483 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000484 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000485 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000486 }
487
Bill Wendlingbed94652010-11-09 23:28:44 +0000488 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000489 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
490 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000491 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000492 }
493
Kevin Enderbyf5079942009-10-13 22:19:02 +0000494 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000495 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000496 return Imm.Val;
497 }
498
Jim Grosbache7fbce72011-10-03 23:38:36 +0000499 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000500 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000501 return FPImm.Val;
502 }
503
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000504 unsigned getVectorIndex() const {
505 assert(Kind == k_VectorIndex && "Invalid access!");
506 return VectorIndex.Val;
507 }
508
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000509 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000510 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000511 return MBOpt.Val;
512 }
513
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000514 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000515 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000516 return IFlags.Val;
517 }
518
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000519 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000520 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000521 return MMask.Val;
522 }
523
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000524 bool isCoprocNum() const { return Kind == k_CoprocNum; }
525 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000526 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000527 bool isCondCode() const { return Kind == k_CondCode; }
528 bool isCCOut() const { return Kind == k_CCOut; }
529 bool isITMask() const { return Kind == k_ITCondMask; }
530 bool isITCondCode() const { return Kind == k_CondCode; }
531 bool isImm() const { return Kind == k_Immediate; }
532 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000533 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000534 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000535 return false;
536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
537 if (!CE) return false;
538 int64_t Value = CE->getValue();
539 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
540 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000541 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000542 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000543 return false;
544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
545 if (!CE) return false;
546 int64_t Value = CE->getValue();
547 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
548 }
549 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000550 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000551 return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
556 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000557 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000558 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000559 return false;
560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
561 if (!CE) return false;
562 int64_t Value = CE->getValue();
563 return Value >= 0 && Value < 256;
564 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000565 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000566 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000567 return false;
568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
569 if (!CE) return false;
570 int64_t Value = CE->getValue();
571 return Value >= 0 && Value < 8;
572 }
573 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000574 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000575 return false;
576 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
577 if (!CE) return false;
578 int64_t Value = CE->getValue();
579 return Value >= 0 && Value < 16;
580 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000581 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000582 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000583 return false;
584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
585 if (!CE) return false;
586 int64_t Value = CE->getValue();
587 return Value >= 0 && Value < 32;
588 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000589 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000590 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000591 return false;
592 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
593 if (!CE) return false;
594 int64_t Value = CE->getValue();
595 return Value > 0 && Value < 17;
596 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000597 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000598 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000599 return false;
600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
601 if (!CE) return false;
602 int64_t Value = CE->getValue();
603 return Value > 0 && Value < 33;
604 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000605 bool isImm0_32() const {
606 if (Kind != k_Immediate)
607 return false;
608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 33;
612 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000613 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 if (!CE) return false;
618 int64_t Value = CE->getValue();
619 return Value >= 0 && Value < 65536;
620 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000621 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 // If it's not a constant expression, it'll generate a fixup and be
626 // handled later.
627 if (!CE) return true;
628 int64_t Value = CE->getValue();
629 return Value >= 0 && Value < 65536;
630 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000631 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000632 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000633 return false;
634 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
635 if (!CE) return false;
636 int64_t Value = CE->getValue();
637 return Value >= 0 && Value <= 0xffffff;
638 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000639 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000640 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000641 return false;
642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
643 if (!CE) return false;
644 int64_t Value = CE->getValue();
645 return Value > 0 && Value < 33;
646 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000647 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000648 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000649 return false;
650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value >= 0 && Value < 32;
654 }
655 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000656 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000657 return false;
658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
659 if (!CE) return false;
660 int64_t Value = CE->getValue();
661 return Value > 0 && Value <= 32;
662 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000663 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000664 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000665 return false;
666 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
667 if (!CE) return false;
668 int64_t Value = CE->getValue();
669 return ARM_AM::getSOImmVal(Value) != -1;
670 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000671 bool isARMSOImmNot() const {
672 if (Kind != k_Immediate)
673 return false;
674 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
675 if (!CE) return false;
676 int64_t Value = CE->getValue();
677 return ARM_AM::getSOImmVal(~Value) != -1;
678 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000679 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000680 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000681 return false;
682 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
683 if (!CE) return false;
684 int64_t Value = CE->getValue();
685 return ARM_AM::getT2SOImmVal(Value) != -1;
686 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000687 bool isT2SOImmNot() const {
688 if (Kind != k_Immediate)
689 return false;
690 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
691 if (!CE) return false;
692 int64_t Value = CE->getValue();
693 return ARM_AM::getT2SOImmVal(~Value) != -1;
694 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000695 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000696 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000697 return false;
698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
699 if (!CE) return false;
700 int64_t Value = CE->getValue();
701 return Value == 1 || Value == 0;
702 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000703 bool isReg() const { return Kind == k_Register; }
704 bool isRegList() const { return Kind == k_RegisterList; }
705 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
706 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
707 bool isToken() const { return Kind == k_Token; }
708 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
709 bool isMemory() const { return Kind == k_Memory; }
710 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
711 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
712 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
713 bool isRotImm() const { return Kind == k_RotateImmediate; }
714 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
715 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000716 bool isPostIdxReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000717 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000718 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000719 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000720 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000721 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000722 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000723 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
724 (alignOK || Memory.Alignment == 0);
725 }
726 bool isAlignedMemory() const {
727 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000728 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000729 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000730 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000731 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000732 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000733 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000734 if (!Memory.OffsetImm) return true;
735 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000736 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000737 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000738 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000739 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000740 return false;
741 // Immediate offset in range [-4095, 4095].
742 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
743 if (!CE) return false;
744 int64_t Val = CE->getValue();
745 return Val > -4096 && Val < 4096;
746 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000747 bool isAddrMode3() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000748 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000749 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000750 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000751 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000752 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000753 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000754 if (!Memory.OffsetImm) return true;
755 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000756 return Val > -256 && Val < 256;
757 }
758 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000759 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000760 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000761 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000762 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
763 // Immediate offset in range [-255, 255].
764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000767 // Special case, #-0 is INT32_MIN.
768 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000769 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000770 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000771 // If we have an immediate that's not a constant, treat it as a label
772 // reference needing a fixup. If it is a constant, it's something else
773 // and we reject it.
774 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
775 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000776 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000777 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000778 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000779 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000780 if (!Memory.OffsetImm) return true;
781 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000782 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000783 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000784 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000785 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000786 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000787 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000788 return false;
789 return true;
790 }
791 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000792 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000793 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
794 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000795 return false;
796 return true;
797 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000798 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000799 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000800 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000801 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000802 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000803 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000804 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
805 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000806 return false;
807 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000808 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000809 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000810 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000811 return false;
812 return true;
813 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000814 bool isMemThumbRR() const {
815 // Thumb reg+reg addressing is simple. Just two registers, a base and
816 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000817 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000818 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000819 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000820 return isARMLowRegister(Memory.BaseRegNum) &&
821 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000822 }
823 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000824 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000825 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000826 return false;
827 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000828 if (!Memory.OffsetImm) return true;
829 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000830 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
831 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000832 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000833 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000834 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000835 return false;
836 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000837 if (!Memory.OffsetImm) return true;
838 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000839 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
840 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000841 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000842 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000843 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000844 return false;
845 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000846 if (!Memory.OffsetImm) return true;
847 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000848 return Val >= 0 && Val <= 31;
849 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000850 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000851 if (!isMemory() || Memory.OffsetRegNum != 0 ||
852 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000853 return false;
854 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000857 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000858 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000859 bool isMemImm8s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000861 return false;
862 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000865 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
866 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000867 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +0000869 return false;
870 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +0000873 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
874 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000875 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000877 return false;
878 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +0000881 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +0000882 }
Jim Grosbach2392c532011-09-07 23:39:14 +0000883 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +0000885 return false;
886 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +0000889 return Val >= 0 && Val < 256;
890 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000891 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000892 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000893 return false;
894 // Immediate offset in range [-255, -1].
Jim Grosbach871dff72011-10-11 15:59:20 +0000895 if (!Memory.OffsetImm) return true;
896 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000897 return Val > -256 && Val < 0;
898 }
899 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000900 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000901 return false;
902 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000905 return (Val >= 0 && Val < 4096);
906 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000907 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +0000908 // If we have an immediate that's not a constant, treat it as a label
909 // reference needing a fixup. If it is a constant, it's something else
910 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000911 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +0000912 return true;
913
Jim Grosbacha95ec992011-10-11 17:29:55 +0000914 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000915 return false;
916 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000917 if (!Memory.OffsetImm) return true;
918 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000919 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000920 }
921 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000922 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +0000923 return false;
924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
925 if (!CE) return false;
926 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +0000927 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000928 }
Jim Grosbach93981412011-10-11 21:55:36 +0000929 bool isPostIdxImm8s4() const {
930 if (Kind != k_Immediate)
931 return false;
932 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
933 if (!CE) return false;
934 int64_t Val = CE->getValue();
935 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
936 (Val == INT32_MIN);
937 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000938
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000939 bool isMSRMask() const { return Kind == k_MSRMask; }
940 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000941
Jim Grosbach741cd732011-10-17 22:26:03 +0000942 // NEON operands.
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000943 bool isVecListOneD() const {
944 if (Kind != k_VectorList) return false;
945 return VectorList.Count == 1;
946 }
947
Jim Grosbach2f2e3c42011-10-21 18:54:25 +0000948 bool isVecListTwoD() const {
949 if (Kind != k_VectorList) return false;
950 return VectorList.Count == 2;
951 }
952
Jim Grosbachc4360fe2011-10-21 20:02:19 +0000953 bool isVecListThreeD() const {
954 if (Kind != k_VectorList) return false;
955 return VectorList.Count == 3;
956 }
957
Jim Grosbach846bcff2011-10-21 20:35:01 +0000958 bool isVecListFourD() const {
959 if (Kind != k_VectorList) return false;
960 return VectorList.Count == 4;
961 }
962
Jim Grosbach118b38c2011-10-21 22:21:10 +0000963 bool isVecListTwoQ() const {
964 if (Kind != k_VectorList) return false;
965 //FIXME: We haven't taught the parser to handle by-two register lists
966 // yet, so don't pretend to know one.
967 return VectorList.Count == 2 && false;
968 }
969
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000970 bool isVectorIndex8() const {
971 if (Kind != k_VectorIndex) return false;
972 return VectorIndex.Val < 8;
973 }
974 bool isVectorIndex16() const {
975 if (Kind != k_VectorIndex) return false;
976 return VectorIndex.Val < 4;
977 }
978 bool isVectorIndex32() const {
979 if (Kind != k_VectorIndex) return false;
980 return VectorIndex.Val < 2;
981 }
982
Jim Grosbach741cd732011-10-17 22:26:03 +0000983 bool isNEONi8splat() const {
984 if (Kind != k_Immediate)
985 return false;
986 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
987 // Must be a constant.
988 if (!CE) return false;
989 int64_t Value = CE->getValue();
990 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
991 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +0000992 return Value >= 0 && Value < 256;
993 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000994
Jim Grosbachcda32ae2011-10-17 23:09:09 +0000995 bool isNEONi16splat() const {
996 if (Kind != k_Immediate)
997 return false;
998 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
999 // Must be a constant.
1000 if (!CE) return false;
1001 int64_t Value = CE->getValue();
1002 // i16 value in the range [0,255] or [0x0100, 0xff00]
1003 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1004 }
1005
Jim Grosbach8211c052011-10-18 00:22:00 +00001006 bool isNEONi32splat() const {
1007 if (Kind != k_Immediate)
1008 return false;
1009 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1010 // Must be a constant.
1011 if (!CE) return false;
1012 int64_t Value = CE->getValue();
1013 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1014 return (Value >= 0 && Value < 256) ||
1015 (Value >= 0x0100 && Value <= 0xff00) ||
1016 (Value >= 0x010000 && Value <= 0xff0000) ||
1017 (Value >= 0x01000000 && Value <= 0xff000000);
1018 }
1019
1020 bool isNEONi32vmov() const {
1021 if (Kind != k_Immediate)
1022 return false;
1023 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1024 // Must be a constant.
1025 if (!CE) return false;
1026 int64_t Value = CE->getValue();
1027 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1028 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1029 return (Value >= 0 && Value < 256) ||
1030 (Value >= 0x0100 && Value <= 0xff00) ||
1031 (Value >= 0x010000 && Value <= 0xff0000) ||
1032 (Value >= 0x01000000 && Value <= 0xff000000) ||
1033 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1034 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1035 }
1036
Jim Grosbache4454e02011-10-18 16:18:11 +00001037 bool isNEONi64splat() const {
1038 if (Kind != k_Immediate)
1039 return false;
1040 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1041 // Must be a constant.
1042 if (!CE) return false;
1043 uint64_t Value = CE->getValue();
1044 // i64 value with each byte being either 0 or 0xff.
1045 for (unsigned i = 0; i < 8; ++i)
1046 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1047 return true;
1048 }
1049
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001050 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001051 // Add as immediates when possible. Null MCExpr = 0.
1052 if (Expr == 0)
1053 Inst.addOperand(MCOperand::CreateImm(0));
1054 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001055 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1056 else
1057 Inst.addOperand(MCOperand::CreateExpr(Expr));
1058 }
1059
Daniel Dunbard8042b72010-08-11 06:36:53 +00001060 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001061 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001062 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001063 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1064 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001065 }
1066
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001067 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
1069 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1070 }
1071
Jim Grosbach48399582011-10-12 17:34:41 +00001072 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
1074 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1075 }
1076
1077 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
1079 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1080 }
1081
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001082 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1085 }
1086
1087 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1090 }
1091
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001092 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
1094 Inst.addOperand(MCOperand::CreateReg(getReg()));
1095 }
1096
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001097 void addRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 Inst.addOperand(MCOperand::CreateReg(getReg()));
1100 }
1101
Jim Grosbachac798e12011-07-25 20:49:51 +00001102 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001103 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001104 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1105 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1106 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001107 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001108 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001109 }
1110
Jim Grosbachac798e12011-07-25 20:49:51 +00001111 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001112 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001113 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1114 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001115 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001116 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001117 }
1118
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001119 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001120 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001121 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1122 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001123 }
1124
Bill Wendling8d2aa032010-11-08 23:49:57 +00001125 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001126 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001127 const SmallVectorImpl<unsigned> &RegList = getRegList();
1128 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001129 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1130 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001131 }
1132
Bill Wendling9898ac92010-11-17 04:32:08 +00001133 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1134 addRegListOperands(Inst, N);
1135 }
1136
1137 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1138 addRegListOperands(Inst, N);
1139 }
1140
Jim Grosbach833b9d32011-07-27 20:15:40 +00001141 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1142 assert(N == 1 && "Invalid number of operands!");
1143 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1144 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1145 }
1146
Jim Grosbach864b6092011-07-28 21:34:26 +00001147 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1148 assert(N == 1 && "Invalid number of operands!");
1149 // Munge the lsb/width into a bitfield mask.
1150 unsigned lsb = Bitfield.LSB;
1151 unsigned width = Bitfield.Width;
1152 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1153 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1154 (32 - (lsb + width)));
1155 Inst.addOperand(MCOperand::CreateImm(Mask));
1156 }
1157
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001158 void addImmOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 1 && "Invalid number of operands!");
1160 addExpr(Inst, getImm());
1161 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001162
Jim Grosbache7fbce72011-10-03 23:38:36 +00001163 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1164 assert(N == 1 && "Invalid number of operands!");
1165 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1166 }
1167
Jim Grosbach7db8d692011-09-08 22:07:06 +00001168 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
1170 // FIXME: We really want to scale the value here, but the LDRD/STRD
1171 // instruction don't encode operands that way yet.
1172 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1173 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1174 }
1175
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001176 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
1178 // The immediate is scaled by four in the encoding and is stored
1179 // in the MCInst as such. Lop off the low two bits here.
1180 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1181 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1182 }
1183
1184 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 // The immediate is scaled by four in the encoding and is stored
1187 // in the MCInst as such. Lop off the low two bits here.
1188 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1189 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1190 }
1191
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001192 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1193 assert(N == 1 && "Invalid number of operands!");
1194 addExpr(Inst, getImm());
1195 }
1196
Jim Grosbach31756c22011-07-13 22:01:08 +00001197 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1198 assert(N == 1 && "Invalid number of operands!");
1199 addExpr(Inst, getImm());
1200 }
1201
1202 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1203 assert(N == 1 && "Invalid number of operands!");
1204 addExpr(Inst, getImm());
1205 }
1206
Jim Grosbach72e7c4f2011-07-21 23:26:25 +00001207 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1208 assert(N == 1 && "Invalid number of operands!");
1209 addExpr(Inst, getImm());
1210 }
1211
Jim Grosbach475c6db2011-07-25 23:09:14 +00001212 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1213 assert(N == 1 && "Invalid number of operands!");
1214 // The constant encodes as the immediate-1, and we store in the instruction
1215 // the bits as encoded, so subtract off one here.
1216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1217 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1218 }
1219
Jim Grosbach801e0a32011-07-22 23:16:18 +00001220 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1221 assert(N == 1 && "Invalid number of operands!");
1222 // The constant encodes as the immediate-1, and we store in the instruction
1223 // the bits as encoded, so subtract off one here.
1224 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1225 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1226 }
1227
Jim Grosbachc14871c2011-11-10 19:18:01 +00001228 void addImm0_32Operands(MCInst &Inst, unsigned N) const {
1229 assert(N == 1 && "Invalid number of operands!");
1230 addExpr(Inst, getImm());
1231 }
1232
Jim Grosbach975b6412011-07-13 20:10:10 +00001233 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1234 assert(N == 1 && "Invalid number of operands!");
1235 addExpr(Inst, getImm());
1236 }
1237
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00001238 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1239 assert(N == 1 && "Invalid number of operands!");
1240 addExpr(Inst, getImm());
1241 }
1242
Jim Grosbachf1637842011-07-26 16:24:27 +00001243 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1244 assert(N == 1 && "Invalid number of operands!");
1245 addExpr(Inst, getImm());
1246 }
1247
Jim Grosbach46dd4132011-08-17 21:51:27 +00001248 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1249 assert(N == 1 && "Invalid number of operands!");
1250 // The constant encodes as the immediate, except for 32, which encodes as
1251 // zero.
1252 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1253 unsigned Imm = CE->getValue();
1254 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1255 }
1256
Jim Grosbach27c1e252011-07-21 17:23:04 +00001257 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1258 assert(N == 1 && "Invalid number of operands!");
1259 addExpr(Inst, getImm());
1260 }
1261
1262 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1263 assert(N == 1 && "Invalid number of operands!");
1264 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1265 // the instruction as well.
1266 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1267 int Val = CE->getValue();
1268 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1269 }
1270
Jim Grosbach9720dcf2011-07-19 16:50:30 +00001271 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
1273 addExpr(Inst, getImm());
1274 }
1275
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001276 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
1278 addExpr(Inst, getImm());
1279 }
1280
Jim Grosbachb009a872011-10-28 22:36:30 +00001281 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1282 assert(N == 1 && "Invalid number of operands!");
1283 // The operand is actually a t2_so_imm, but we have its bitwise
1284 // negation in the assembly source, so twiddle it here.
1285 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1286 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1287 }
1288
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001289 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
1291 // The operand is actually a so_imm, but we have its bitwise
1292 // negation in the assembly source, so twiddle it here.
1293 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1294 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1295 }
1296
Jim Grosbach0a547702011-07-22 17:44:50 +00001297 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
1299 addExpr(Inst, getImm());
1300 }
1301
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001302 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1303 assert(N == 1 && "Invalid number of operands!");
1304 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1305 }
1306
Jim Grosbachd3595712011-08-03 23:50:40 +00001307 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1308 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001309 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001310 }
1311
Jim Grosbacha95ec992011-10-11 17:29:55 +00001312 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1313 assert(N == 2 && "Invalid number of operands!");
1314 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1315 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1316 }
1317
Jim Grosbachd3595712011-08-03 23:50:40 +00001318 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1319 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001320 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1321 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001322 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1323 // Special case for #-0
1324 if (Val == INT32_MIN) Val = 0;
1325 if (Val < 0) Val = -Val;
1326 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1327 } else {
1328 // For register offset, we encode the shift type and negation flag
1329 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001330 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1331 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001332 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001333 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1334 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001335 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001336 }
1337
Jim Grosbachcd17c122011-08-04 23:01:30 +00001338 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1339 assert(N == 2 && "Invalid number of operands!");
1340 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1341 assert(CE && "non-constant AM2OffsetImm operand!");
1342 int32_t Val = CE->getValue();
1343 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1344 // Special case for #-0
1345 if (Val == INT32_MIN) Val = 0;
1346 if (Val < 0) Val = -Val;
1347 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1348 Inst.addOperand(MCOperand::CreateReg(0));
1349 Inst.addOperand(MCOperand::CreateImm(Val));
1350 }
1351
Jim Grosbach5b96b802011-08-10 20:29:19 +00001352 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001354 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1355 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001356 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1357 // Special case for #-0
1358 if (Val == INT32_MIN) Val = 0;
1359 if (Val < 0) Val = -Val;
1360 Val = ARM_AM::getAM3Opc(AddSub, Val);
1361 } else {
1362 // For register offset, we encode the shift type and negation flag
1363 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001364 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001365 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001366 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1367 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001368 Inst.addOperand(MCOperand::CreateImm(Val));
1369 }
1370
1371 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1372 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001373 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001374 int32_t Val =
1375 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1376 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1377 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001378 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001379 }
1380
1381 // Constant offset.
1382 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1383 int32_t Val = CE->getValue();
1384 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1385 // Special case for #-0
1386 if (Val == INT32_MIN) Val = 0;
1387 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001388 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001389 Inst.addOperand(MCOperand::CreateReg(0));
1390 Inst.addOperand(MCOperand::CreateImm(Val));
1391 }
1392
Jim Grosbachd3595712011-08-03 23:50:40 +00001393 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1394 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001395 // If we have an immediate that's not a constant, treat it as a label
1396 // reference needing a fixup. If it is a constant, it's something else
1397 // and we reject it.
1398 if (isImm()) {
1399 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1400 Inst.addOperand(MCOperand::CreateImm(0));
1401 return;
1402 }
1403
Jim Grosbachd3595712011-08-03 23:50:40 +00001404 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001405 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001406 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1407 // Special case for #-0
1408 if (Val == INT32_MIN) Val = 0;
1409 if (Val < 0) Val = -Val;
1410 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001411 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001412 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001413 }
1414
Jim Grosbach7db8d692011-09-08 22:07:06 +00001415 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1416 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001417 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1418 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001419 Inst.addOperand(MCOperand::CreateImm(Val));
1420 }
1421
Jim Grosbacha05627e2011-09-09 18:37:27 +00001422 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1423 assert(N == 2 && "Invalid number of operands!");
1424 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001425 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1426 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001427 Inst.addOperand(MCOperand::CreateImm(Val));
1428 }
1429
Jim Grosbachd3595712011-08-03 23:50:40 +00001430 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001432 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1433 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001434 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001435 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001436
Jim Grosbach2392c532011-09-07 23:39:14 +00001437 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1438 addMemImm8OffsetOperands(Inst, N);
1439 }
1440
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001441 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001442 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001443 }
1444
1445 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 2 && "Invalid number of operands!");
1447 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001448 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001449 addExpr(Inst, getImm());
1450 Inst.addOperand(MCOperand::CreateImm(0));
1451 return;
1452 }
1453
1454 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001455 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1456 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001457 Inst.addOperand(MCOperand::CreateImm(Val));
1458 }
1459
Jim Grosbachd3595712011-08-03 23:50:40 +00001460 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001462 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001463 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001464 addExpr(Inst, getImm());
1465 Inst.addOperand(MCOperand::CreateImm(0));
1466 return;
1467 }
1468
1469 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001470 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1471 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001472 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001473 }
Bill Wendling811c9362010-11-30 07:44:32 +00001474
Jim Grosbach05541f42011-09-19 22:21:13 +00001475 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001477 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1478 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001479 }
1480
1481 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1482 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001483 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1484 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001485 }
1486
Jim Grosbachd3595712011-08-03 23:50:40 +00001487 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1488 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001489 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1490 Memory.ShiftImm, Memory.ShiftType);
1491 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1492 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001493 Inst.addOperand(MCOperand::CreateImm(Val));
1494 }
1495
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001496 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001498 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1499 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1500 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001501 }
1502
Jim Grosbachd3595712011-08-03 23:50:40 +00001503 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001505 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1506 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001507 }
1508
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001509 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1510 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001511 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1512 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001513 Inst.addOperand(MCOperand::CreateImm(Val));
1514 }
1515
Jim Grosbach26d35872011-08-19 18:55:51 +00001516 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1517 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001518 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1519 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001520 Inst.addOperand(MCOperand::CreateImm(Val));
1521 }
1522
Jim Grosbacha32c7532011-08-19 18:49:59 +00001523 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1524 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001525 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1526 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001527 Inst.addOperand(MCOperand::CreateImm(Val));
1528 }
1529
Jim Grosbach23983d62011-08-19 18:13:48 +00001530 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001532 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1533 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001534 Inst.addOperand(MCOperand::CreateImm(Val));
1535 }
1536
Jim Grosbachd3595712011-08-03 23:50:40 +00001537 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1538 assert(N == 1 && "Invalid number of operands!");
1539 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1540 assert(CE && "non-constant post-idx-imm8 operand!");
1541 int Imm = CE->getValue();
1542 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001543 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001544 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1545 Inst.addOperand(MCOperand::CreateImm(Imm));
1546 }
1547
Jim Grosbach93981412011-10-11 21:55:36 +00001548 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1549 assert(N == 1 && "Invalid number of operands!");
1550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1551 assert(CE && "non-constant post-idx-imm8s4 operand!");
1552 int Imm = CE->getValue();
1553 bool isAdd = Imm >= 0;
1554 if (Imm == INT32_MIN) Imm = 0;
1555 // Immediate is scaled by 4.
1556 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1557 Inst.addOperand(MCOperand::CreateImm(Imm));
1558 }
1559
Jim Grosbachd3595712011-08-03 23:50:40 +00001560 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 2 && "Invalid number of operands!");
1562 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001563 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1564 }
1565
1566 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 2 && "Invalid number of operands!");
1568 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1569 // The sign, shift type, and shift amount are encoded in a single operand
1570 // using the AM2 encoding helpers.
1571 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1572 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1573 PostIdxReg.ShiftTy);
1574 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001575 }
1576
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001577 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
1579 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1580 }
1581
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001582 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
1584 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1585 }
1586
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001587 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1590 }
1591
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001592 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1593 assert(N == 1 && "Invalid number of operands!");
1594 // Only the first register actually goes on the instruction. The rest
1595 // are implied by the opcode.
1596 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1597 }
1598
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001599 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1600 assert(N == 1 && "Invalid number of operands!");
1601 // Only the first register actually goes on the instruction. The rest
1602 // are implied by the opcode.
1603 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1604 }
1605
Jim Grosbach846bcff2011-10-21 20:35:01 +00001606 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 1 && "Invalid number of operands!");
1608 // Only the first register actually goes on the instruction. The rest
1609 // are implied by the opcode.
1610 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1611 }
1612
Jim Grosbach118b38c2011-10-21 22:21:10 +00001613 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 // Only the first register actually goes on the instruction. The rest
1616 // are implied by the opcode.
1617 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1618 }
1619
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001620 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1621 assert(N == 1 && "Invalid number of operands!");
1622 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1623 }
1624
1625 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1626 assert(N == 1 && "Invalid number of operands!");
1627 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1628 }
1629
1630 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1631 assert(N == 1 && "Invalid number of operands!");
1632 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1633 }
1634
Jim Grosbach741cd732011-10-17 22:26:03 +00001635 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1636 assert(N == 1 && "Invalid number of operands!");
1637 // The immediate encodes the type of constant as well as the value.
1638 // Mask in that this is an i8 splat.
1639 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1640 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1641 }
1642
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001643 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1644 assert(N == 1 && "Invalid number of operands!");
1645 // The immediate encodes the type of constant as well as the value.
1646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1647 unsigned Value = CE->getValue();
1648 if (Value >= 256)
1649 Value = (Value >> 8) | 0xa00;
1650 else
1651 Value |= 0x800;
1652 Inst.addOperand(MCOperand::CreateImm(Value));
1653 }
1654
Jim Grosbach8211c052011-10-18 00:22:00 +00001655 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1656 assert(N == 1 && "Invalid number of operands!");
1657 // The immediate encodes the type of constant as well as the value.
1658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1659 unsigned Value = CE->getValue();
1660 if (Value >= 256 && Value <= 0xff00)
1661 Value = (Value >> 8) | 0x200;
1662 else if (Value > 0xffff && Value <= 0xff0000)
1663 Value = (Value >> 16) | 0x400;
1664 else if (Value > 0xffffff)
1665 Value = (Value >> 24) | 0x600;
1666 Inst.addOperand(MCOperand::CreateImm(Value));
1667 }
1668
1669 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1670 assert(N == 1 && "Invalid number of operands!");
1671 // The immediate encodes the type of constant as well as the value.
1672 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1673 unsigned Value = CE->getValue();
1674 if (Value >= 256 && Value <= 0xffff)
1675 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1676 else if (Value > 0xffff && Value <= 0xffffff)
1677 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1678 else if (Value > 0xffffff)
1679 Value = (Value >> 24) | 0x600;
1680 Inst.addOperand(MCOperand::CreateImm(Value));
1681 }
1682
Jim Grosbache4454e02011-10-18 16:18:11 +00001683 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1684 assert(N == 1 && "Invalid number of operands!");
1685 // The immediate encodes the type of constant as well as the value.
1686 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1687 uint64_t Value = CE->getValue();
1688 unsigned Imm = 0;
1689 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1690 Imm |= (Value & 1) << i;
1691 }
1692 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1693 }
1694
Jim Grosbach602aa902011-07-13 15:34:57 +00001695 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001696
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001697 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001698 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001699 Op->ITMask.Mask = Mask;
1700 Op->StartLoc = S;
1701 Op->EndLoc = S;
1702 return Op;
1703 }
1704
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001705 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001706 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001707 Op->CC.Val = CC;
1708 Op->StartLoc = S;
1709 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001710 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001711 }
1712
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001713 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001714 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001715 Op->Cop.Val = CopVal;
1716 Op->StartLoc = S;
1717 Op->EndLoc = S;
1718 return Op;
1719 }
1720
1721 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001722 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001723 Op->Cop.Val = CopVal;
1724 Op->StartLoc = S;
1725 Op->EndLoc = S;
1726 return Op;
1727 }
1728
Jim Grosbach48399582011-10-12 17:34:41 +00001729 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1730 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1731 Op->Cop.Val = Val;
1732 Op->StartLoc = S;
1733 Op->EndLoc = E;
1734 return Op;
1735 }
1736
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001737 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001738 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001739 Op->Reg.RegNum = RegNum;
1740 Op->StartLoc = S;
1741 Op->EndLoc = S;
1742 return Op;
1743 }
1744
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001745 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001746 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001747 Op->Tok.Data = Str.data();
1748 Op->Tok.Length = Str.size();
1749 Op->StartLoc = S;
1750 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001751 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001752 }
1753
Bill Wendling2063b842010-11-18 23:43:05 +00001754 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001755 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001756 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001757 Op->StartLoc = S;
1758 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001759 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001760 }
1761
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001762 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1763 unsigned SrcReg,
1764 unsigned ShiftReg,
1765 unsigned ShiftImm,
1766 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001767 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001768 Op->RegShiftedReg.ShiftTy = ShTy;
1769 Op->RegShiftedReg.SrcReg = SrcReg;
1770 Op->RegShiftedReg.ShiftReg = ShiftReg;
1771 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001772 Op->StartLoc = S;
1773 Op->EndLoc = E;
1774 return Op;
1775 }
1776
Owen Andersonb595ed02011-07-21 18:54:16 +00001777 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1778 unsigned SrcReg,
1779 unsigned ShiftImm,
1780 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001781 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001782 Op->RegShiftedImm.ShiftTy = ShTy;
1783 Op->RegShiftedImm.SrcReg = SrcReg;
1784 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001785 Op->StartLoc = S;
1786 Op->EndLoc = E;
1787 return Op;
1788 }
1789
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001790 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001791 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001792 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001793 Op->ShifterImm.isASR = isASR;
1794 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001795 Op->StartLoc = S;
1796 Op->EndLoc = E;
1797 return Op;
1798 }
1799
Jim Grosbach833b9d32011-07-27 20:15:40 +00001800 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001801 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001802 Op->RotImm.Imm = Imm;
1803 Op->StartLoc = S;
1804 Op->EndLoc = E;
1805 return Op;
1806 }
1807
Jim Grosbach864b6092011-07-28 21:34:26 +00001808 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1809 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001810 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001811 Op->Bitfield.LSB = LSB;
1812 Op->Bitfield.Width = Width;
1813 Op->StartLoc = S;
1814 Op->EndLoc = E;
1815 return Op;
1816 }
1817
Bill Wendling2cae3272010-11-09 22:44:22 +00001818 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001819 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001820 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001821 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001822
Jim Grosbach75461af2011-09-13 22:56:44 +00001823 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001824 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001825 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001826 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001827 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001828
1829 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001830 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001831 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001832 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001833 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001834 Op->StartLoc = StartLoc;
1835 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001836 return Op;
1837 }
1838
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001839 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1840 SMLoc S, SMLoc E) {
1841 ARMOperand *Op = new ARMOperand(k_VectorList);
1842 Op->VectorList.RegNum = RegNum;
1843 Op->VectorList.Count = Count;
1844 Op->StartLoc = S;
1845 Op->EndLoc = E;
1846 return Op;
1847 }
1848
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001849 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1850 MCContext &Ctx) {
1851 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1852 Op->VectorIndex.Val = Idx;
1853 Op->StartLoc = S;
1854 Op->EndLoc = E;
1855 return Op;
1856 }
1857
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001858 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001859 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001860 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001861 Op->StartLoc = S;
1862 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001863 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001864 }
1865
Jim Grosbache7fbce72011-10-03 23:38:36 +00001866 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001867 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00001868 Op->FPImm.Val = Val;
1869 Op->StartLoc = S;
1870 Op->EndLoc = S;
1871 return Op;
1872 }
1873
Jim Grosbachd3595712011-08-03 23:50:40 +00001874 static ARMOperand *CreateMem(unsigned BaseRegNum,
1875 const MCConstantExpr *OffsetImm,
1876 unsigned OffsetRegNum,
1877 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001878 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00001879 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00001880 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001881 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001882 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00001883 Op->Memory.BaseRegNum = BaseRegNum;
1884 Op->Memory.OffsetImm = OffsetImm;
1885 Op->Memory.OffsetRegNum = OffsetRegNum;
1886 Op->Memory.ShiftType = ShiftType;
1887 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001888 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00001889 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00001890 Op->StartLoc = S;
1891 Op->EndLoc = E;
1892 return Op;
1893 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001894
Jim Grosbachc320c852011-08-05 21:28:30 +00001895 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1896 ARM_AM::ShiftOpc ShiftTy,
1897 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001898 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001899 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00001900 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00001901 Op->PostIdxReg.isAdd = isAdd;
1902 Op->PostIdxReg.ShiftTy = ShiftTy;
1903 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001904 Op->StartLoc = S;
1905 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001906 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001907 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001908
1909 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001910 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001911 Op->MBOpt.Val = Opt;
1912 Op->StartLoc = S;
1913 Op->EndLoc = S;
1914 return Op;
1915 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001916
1917 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001918 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001919 Op->IFlags.Val = IFlags;
1920 Op->StartLoc = S;
1921 Op->EndLoc = S;
1922 return Op;
1923 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001924
1925 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001926 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001927 Op->MMask.Val = MMask;
1928 Op->StartLoc = S;
1929 Op->EndLoc = S;
1930 return Op;
1931 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001932};
1933
1934} // end anonymous namespace.
1935
Jim Grosbach602aa902011-07-13 15:34:57 +00001936void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001937 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001938 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00001939 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1940 << ") >";
1941 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001942 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00001943 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001944 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001945 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001946 OS << "<ccout " << getReg() << ">";
1947 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001948 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00001949 static const char *MaskStr[] = {
1950 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1951 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1952 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001953 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1954 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1955 break;
1956 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001957 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001958 OS << "<coprocessor number: " << getCoproc() << ">";
1959 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001960 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001961 OS << "<coprocessor register: " << getCoproc() << ">";
1962 break;
Jim Grosbach48399582011-10-12 17:34:41 +00001963 case k_CoprocOption:
1964 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1965 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001966 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001967 OS << "<mask: " << getMSRMask() << ">";
1968 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001969 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001970 getImm()->print(OS);
1971 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001972 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001973 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1974 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001975 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001976 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00001977 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001978 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001979 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001980 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00001981 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1982 << PostIdxReg.RegNum;
1983 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1984 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1985 << PostIdxReg.ShiftImm;
1986 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00001987 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001988 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001989 OS << "<ARM_PROC::";
1990 unsigned IFlags = getProcIFlags();
1991 for (int i=2; i >= 0; --i)
1992 if (IFlags & (1 << i))
1993 OS << ARM_PROC::IFlagsToString(1 << i);
1994 OS << ">";
1995 break;
1996 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001997 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00001998 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001999 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002000 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002001 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2002 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002003 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002004 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002005 OS << "<so_reg_reg "
Jim Grosbachac798e12011-07-25 20:49:51 +00002006 << RegShiftedReg.SrcReg
2007 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
2008 << ", " << RegShiftedReg.ShiftReg << ", "
2009 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002010 << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002011 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002012 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002013 OS << "<so_reg_imm "
Jim Grosbachac798e12011-07-25 20:49:51 +00002014 << RegShiftedImm.SrcReg
2015 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
2016 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Andersonb595ed02011-07-21 18:54:16 +00002017 << ">";
2018 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002019 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002020 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2021 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002022 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002023 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2024 << ", width: " << Bitfield.Width << ">";
2025 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002026 case k_RegisterList:
2027 case k_DPRRegisterList:
2028 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002029 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002030
Bill Wendlingbed94652010-11-09 23:28:44 +00002031 const SmallVectorImpl<unsigned> &RegList = getRegList();
2032 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002033 I = RegList.begin(), E = RegList.end(); I != E; ) {
2034 OS << *I;
2035 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002036 }
2037
2038 OS << ">";
2039 break;
2040 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002041 case k_VectorList:
2042 OS << "<vector_list " << VectorList.Count << " * "
2043 << VectorList.RegNum << ">";
2044 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002045 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002046 OS << "'" << getToken() << "'";
2047 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002048 case k_VectorIndex:
2049 OS << "<vectorindex " << getVectorIndex() << ">";
2050 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002051 }
2052}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002053
2054/// @name Auto-generated Match Functions
2055/// {
2056
2057static unsigned MatchRegisterName(StringRef Name);
2058
2059/// }
2060
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002061bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2062 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002063 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00002064
2065 return (RegNo == (unsigned)-1);
2066}
2067
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002068/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002069/// and if it is a register name the token is eaten and the register number is
2070/// returned. Otherwise return -1.
2071///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002072int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002073 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002074 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002075
Chris Lattner44e5981c2010-10-30 04:09:10 +00002076 // FIXME: Validate register for the current architecture; we have to do
2077 // validation later, so maybe there is no need for this here.
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002078 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002079 unsigned RegNum = MatchRegisterName(lowerCase);
2080 if (!RegNum) {
2081 RegNum = StringSwitch<unsigned>(lowerCase)
2082 .Case("r13", ARM::SP)
2083 .Case("r14", ARM::LR)
2084 .Case("r15", ARM::PC)
2085 .Case("ip", ARM::R12)
2086 .Default(0);
2087 }
2088 if (!RegNum) return -1;
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002089
Chris Lattner44e5981c2010-10-30 04:09:10 +00002090 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002091
Chris Lattner44e5981c2010-10-30 04:09:10 +00002092 return RegNum;
2093}
Jim Grosbach99710a82010-11-01 16:44:21 +00002094
Jim Grosbachbb24c592011-07-13 18:49:30 +00002095// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2096// If a recoverable error occurs, return 1. If an irrecoverable error
2097// occurs, return -1. An irrecoverable error is one where tokens have been
2098// consumed in the process of trying to parse the shifter (i.e., when it is
2099// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002100int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002101 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2102 SMLoc S = Parser.getTok().getLoc();
2103 const AsmToken &Tok = Parser.getTok();
2104 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2105
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002106 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002107 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2108 .Case("lsl", ARM_AM::lsl)
2109 .Case("lsr", ARM_AM::lsr)
2110 .Case("asr", ARM_AM::asr)
2111 .Case("ror", ARM_AM::ror)
2112 .Case("rrx", ARM_AM::rrx)
2113 .Default(ARM_AM::no_shift);
2114
2115 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002116 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002117
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002118 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002119
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002120 // The source register for the shift has already been added to the
2121 // operand list, so we need to pop it off and combine it into the shifted
2122 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002123 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002124 if (!PrevOp->isReg())
2125 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2126 int SrcReg = PrevOp->getReg();
2127 int64_t Imm = 0;
2128 int ShiftReg = 0;
2129 if (ShiftTy == ARM_AM::rrx) {
2130 // RRX Doesn't have an explicit shift amount. The encoder expects
2131 // the shift register to be the same as the source register. Seems odd,
2132 // but OK.
2133 ShiftReg = SrcReg;
2134 } else {
2135 // Figure out if this is shifted by a constant or a register (for non-RRX).
2136 if (Parser.getTok().is(AsmToken::Hash)) {
2137 Parser.Lex(); // Eat hash.
2138 SMLoc ImmLoc = Parser.getTok().getLoc();
2139 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002140 if (getParser().ParseExpression(ShiftExpr)) {
2141 Error(ImmLoc, "invalid immediate shift value");
2142 return -1;
2143 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002144 // The expression must be evaluatable as an immediate.
2145 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002146 if (!CE) {
2147 Error(ImmLoc, "invalid immediate shift value");
2148 return -1;
2149 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002150 // Range check the immediate.
2151 // lsl, ror: 0 <= imm <= 31
2152 // lsr, asr: 0 <= imm <= 32
2153 Imm = CE->getValue();
2154 if (Imm < 0 ||
2155 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2156 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002157 Error(ImmLoc, "immediate shift value out of range");
2158 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002159 }
2160 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002161 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002162 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002163 if (ShiftReg == -1) {
2164 Error (L, "expected immediate or register in shift operand");
2165 return -1;
2166 }
2167 } else {
2168 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002169 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002170 return -1;
2171 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002172 }
2173
Owen Andersonb595ed02011-07-21 18:54:16 +00002174 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2175 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002176 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002177 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002178 else
2179 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2180 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002181
Jim Grosbachbb24c592011-07-13 18:49:30 +00002182 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002183}
2184
2185
Bill Wendling2063b842010-11-18 23:43:05 +00002186/// Try to parse a register name. The token must be an Identifier when called.
2187/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2188/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002189///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002190/// TODO this is likely to change to allow different register types and or to
2191/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002192bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002193tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002194 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002195 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002196 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002197 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002198
Bill Wendling2063b842010-11-18 23:43:05 +00002199 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002200
Chris Lattner44e5981c2010-10-30 04:09:10 +00002201 const AsmToken &ExclaimTok = Parser.getTok();
2202 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002203 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2204 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002205 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002206 return false;
2207 }
2208
2209 // Also check for an index operand. This is only legal for vector registers,
2210 // but that'll get caught OK in operand matching, so we don't need to
2211 // explicitly filter everything else out here.
2212 if (Parser.getTok().is(AsmToken::LBrac)) {
2213 SMLoc SIdx = Parser.getTok().getLoc();
2214 Parser.Lex(); // Eat left bracket token.
2215
2216 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002217 if (getParser().ParseExpression(ImmVal))
2218 return MatchOperand_ParseFail;
2219 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2220 if (!MCE) {
2221 TokError("immediate value expected for vector index");
2222 return MatchOperand_ParseFail;
2223 }
2224
2225 SMLoc E = Parser.getTok().getLoc();
2226 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2227 Error(E, "']' expected");
2228 return MatchOperand_ParseFail;
2229 }
2230
2231 Parser.Lex(); // Eat right bracket token.
2232
2233 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2234 SIdx, E,
2235 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002236 }
2237
Bill Wendling2063b842010-11-18 23:43:05 +00002238 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002239}
2240
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002241/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2242/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2243/// "c5", ...
2244static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002245 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2246 // but efficient.
2247 switch (Name.size()) {
2248 default: break;
2249 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002250 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002251 return -1;
2252 switch (Name[1]) {
2253 default: return -1;
2254 case '0': return 0;
2255 case '1': return 1;
2256 case '2': return 2;
2257 case '3': return 3;
2258 case '4': return 4;
2259 case '5': return 5;
2260 case '6': return 6;
2261 case '7': return 7;
2262 case '8': return 8;
2263 case '9': return 9;
2264 }
2265 break;
2266 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002267 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002268 return -1;
2269 switch (Name[2]) {
2270 default: return -1;
2271 case '0': return 10;
2272 case '1': return 11;
2273 case '2': return 12;
2274 case '3': return 13;
2275 case '4': return 14;
2276 case '5': return 15;
2277 }
2278 break;
2279 }
2280
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002281 return -1;
2282}
2283
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002284/// parseITCondCode - Try to parse a condition code for an IT instruction.
2285ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2286parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2287 SMLoc S = Parser.getTok().getLoc();
2288 const AsmToken &Tok = Parser.getTok();
2289 if (!Tok.is(AsmToken::Identifier))
2290 return MatchOperand_NoMatch;
2291 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2292 .Case("eq", ARMCC::EQ)
2293 .Case("ne", ARMCC::NE)
2294 .Case("hs", ARMCC::HS)
2295 .Case("cs", ARMCC::HS)
2296 .Case("lo", ARMCC::LO)
2297 .Case("cc", ARMCC::LO)
2298 .Case("mi", ARMCC::MI)
2299 .Case("pl", ARMCC::PL)
2300 .Case("vs", ARMCC::VS)
2301 .Case("vc", ARMCC::VC)
2302 .Case("hi", ARMCC::HI)
2303 .Case("ls", ARMCC::LS)
2304 .Case("ge", ARMCC::GE)
2305 .Case("lt", ARMCC::LT)
2306 .Case("gt", ARMCC::GT)
2307 .Case("le", ARMCC::LE)
2308 .Case("al", ARMCC::AL)
2309 .Default(~0U);
2310 if (CC == ~0U)
2311 return MatchOperand_NoMatch;
2312 Parser.Lex(); // Eat the token.
2313
2314 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2315
2316 return MatchOperand_Success;
2317}
2318
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002319/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002320/// token must be an Identifier when called, and if it is a coprocessor
2321/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002322ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002323parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002324 SMLoc S = Parser.getTok().getLoc();
2325 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002326 if (Tok.isNot(AsmToken::Identifier))
2327 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002328
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002329 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002330 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002331 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002332
2333 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002334 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002335 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002336}
2337
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002338/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002339/// token must be an Identifier when called, and if it is a coprocessor
2340/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002341ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002342parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002343 SMLoc S = Parser.getTok().getLoc();
2344 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002345 if (Tok.isNot(AsmToken::Identifier))
2346 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002347
2348 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2349 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002350 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002351
2352 Parser.Lex(); // Eat identifier token.
2353 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002354 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002355}
2356
Jim Grosbach48399582011-10-12 17:34:41 +00002357/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2358/// coproc_option : '{' imm0_255 '}'
2359ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2360parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2361 SMLoc S = Parser.getTok().getLoc();
2362
2363 // If this isn't a '{', this isn't a coprocessor immediate operand.
2364 if (Parser.getTok().isNot(AsmToken::LCurly))
2365 return MatchOperand_NoMatch;
2366 Parser.Lex(); // Eat the '{'
2367
2368 const MCExpr *Expr;
2369 SMLoc Loc = Parser.getTok().getLoc();
2370 if (getParser().ParseExpression(Expr)) {
2371 Error(Loc, "illegal expression");
2372 return MatchOperand_ParseFail;
2373 }
2374 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2375 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2376 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2377 return MatchOperand_ParseFail;
2378 }
2379 int Val = CE->getValue();
2380
2381 // Check for and consume the closing '}'
2382 if (Parser.getTok().isNot(AsmToken::RCurly))
2383 return MatchOperand_ParseFail;
2384 SMLoc E = Parser.getTok().getLoc();
2385 Parser.Lex(); // Eat the '}'
2386
2387 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2388 return MatchOperand_Success;
2389}
2390
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002391// For register list parsing, we need to map from raw GPR register numbering
2392// to the enumeration values. The enumeration values aren't sorted by
2393// register number due to our using "sp", "lr" and "pc" as canonical names.
2394static unsigned getNextRegister(unsigned Reg) {
2395 // If this is a GPR, we need to do it manually, otherwise we can rely
2396 // on the sort ordering of the enumeration since the other reg-classes
2397 // are sane.
2398 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2399 return Reg + 1;
2400 switch(Reg) {
2401 default: assert(0 && "Invalid GPR number!");
2402 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2403 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2404 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2405 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2406 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2407 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2408 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2409 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2410 }
2411}
2412
2413/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002414bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002415parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002416 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002417 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002418 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002419 Parser.Lex(); // Eat '{' token.
2420 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002421
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002422 // Check the first register in the list to see what register class
2423 // this is a list of.
2424 int Reg = tryParseRegister();
2425 if (Reg == -1)
2426 return Error(RegLoc, "register expected");
2427
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002428 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002429 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2430 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2431 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2432 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2433 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2434 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2435 else
2436 return Error(RegLoc, "invalid register in register list");
2437
2438 // The reglist instructions have at most 16 registers, so reserve
2439 // space for that many.
Jim Grosbache3a6a822011-09-13 20:35:57 +00002440 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002441 // Store the first register.
2442 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002443
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002444 // This starts immediately after the first register token in the list,
2445 // so we can see either a comma or a minus (range separator) as a legal
2446 // next token.
2447 while (Parser.getTok().is(AsmToken::Comma) ||
2448 Parser.getTok().is(AsmToken::Minus)) {
2449 if (Parser.getTok().is(AsmToken::Minus)) {
2450 Parser.Lex(); // Eat the comma.
2451 SMLoc EndLoc = Parser.getTok().getLoc();
2452 int EndReg = tryParseRegister();
2453 if (EndReg == -1)
2454 return Error(EndLoc, "register expected");
2455 // If the register is the same as the start reg, there's nothing
2456 // more to do.
2457 if (Reg == EndReg)
2458 continue;
2459 // The register must be in the same register class as the first.
2460 if (!RC->contains(EndReg))
2461 return Error(EndLoc, "invalid register in register list");
2462 // Ranges must go from low to high.
2463 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2464 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002465
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002466 // Add all the registers in the range to the register list.
2467 while (Reg != EndReg) {
2468 Reg = getNextRegister(Reg);
2469 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2470 }
2471 continue;
2472 }
2473 Parser.Lex(); // Eat the comma.
2474 RegLoc = Parser.getTok().getLoc();
2475 int OldReg = Reg;
2476 Reg = tryParseRegister();
2477 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002478 return Error(RegLoc, "register expected");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002479 // The register must be in the same register class as the first.
2480 if (!RC->contains(Reg))
2481 return Error(RegLoc, "invalid register in register list");
2482 // List must be monotonically increasing.
2483 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2484 return Error(RegLoc, "register list not in ascending order");
2485 // VFP register lists must also be contiguous.
2486 // It's OK to use the enumeration values directly here rather, as the
2487 // VFP register classes have the enum sorted properly.
2488 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2489 Reg != OldReg + 1)
2490 return Error(RegLoc, "non-contiguous register range");
2491 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002492 }
2493
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002494 SMLoc E = Parser.getTok().getLoc();
2495 if (Parser.getTok().isNot(AsmToken::RCurly))
2496 return Error(E, "'}' expected");
2497 Parser.Lex(); // Eat '}' token.
2498
Bill Wendling2063b842010-11-18 23:43:05 +00002499 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2500 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002501}
2502
Jim Grosbach080a4992011-10-28 00:06:50 +00002503// Return the low-subreg of a given Q register.
2504static unsigned getDRegFromQReg(unsigned QReg) {
2505 switch (QReg) {
2506 default: llvm_unreachable("expected a Q register!");
2507 case ARM::Q0: return ARM::D0;
2508 case ARM::Q1: return ARM::D2;
2509 case ARM::Q2: return ARM::D4;
2510 case ARM::Q3: return ARM::D6;
2511 case ARM::Q4: return ARM::D8;
2512 case ARM::Q5: return ARM::D10;
2513 case ARM::Q6: return ARM::D12;
2514 case ARM::Q7: return ARM::D14;
2515 case ARM::Q8: return ARM::D16;
2516 case ARM::Q9: return ARM::D19;
2517 case ARM::Q10: return ARM::D20;
2518 case ARM::Q11: return ARM::D22;
2519 case ARM::Q12: return ARM::D24;
2520 case ARM::Q13: return ARM::D26;
2521 case ARM::Q14: return ARM::D28;
2522 case ARM::Q15: return ARM::D30;
2523 }
2524}
2525
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002526// parse a vector register list
2527ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2528parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2529 if(Parser.getTok().isNot(AsmToken::LCurly))
2530 return MatchOperand_NoMatch;
2531
2532 SMLoc S = Parser.getTok().getLoc();
2533 Parser.Lex(); // Eat '{' token.
2534 SMLoc RegLoc = Parser.getTok().getLoc();
2535
2536 int Reg = tryParseRegister();
2537 if (Reg == -1) {
2538 Error(RegLoc, "register expected");
2539 return MatchOperand_ParseFail;
2540 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002541 unsigned Count = 1;
Jim Grosbach080a4992011-10-28 00:06:50 +00002542 unsigned FirstReg = Reg;
2543 // The list is of D registers, but we also allow Q regs and just interpret
2544 // them as the two D sub-registers.
2545 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2546 FirstReg = Reg = getDRegFromQReg(Reg);
2547 ++Reg;
2548 ++Count;
2549 }
2550
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002551 while (Parser.getTok().is(AsmToken::Comma)) {
2552 Parser.Lex(); // Eat the comma.
2553 RegLoc = Parser.getTok().getLoc();
2554 int OldReg = Reg;
2555 Reg = tryParseRegister();
2556 if (Reg == -1) {
2557 Error(RegLoc, "register expected");
2558 return MatchOperand_ParseFail;
2559 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002560 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002561 // It's OK to use the enumeration values directly here rather, as the
2562 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002563 //
2564 // The list is of D registers, but we also allow Q regs and just interpret
2565 // them as the two D sub-registers.
2566 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2567 Reg = getDRegFromQReg(Reg);
2568 if (Reg != OldReg + 1) {
2569 Error(RegLoc, "non-contiguous register range");
2570 return MatchOperand_ParseFail;
2571 }
2572 ++Reg;
2573 Count += 2;
2574 continue;
2575 }
2576 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002577 if (Reg != OldReg + 1) {
2578 Error(RegLoc, "non-contiguous register range");
2579 return MatchOperand_ParseFail;
2580 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002581 ++Count;
2582 }
2583
2584 SMLoc E = Parser.getTok().getLoc();
2585 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2586 Error(E, "'}' expected");
2587 return MatchOperand_ParseFail;
2588 }
2589 Parser.Lex(); // Eat '}' token.
2590
2591 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2592 return MatchOperand_Success;
2593}
2594
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002595/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002596ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002597parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002598 SMLoc S = Parser.getTok().getLoc();
2599 const AsmToken &Tok = Parser.getTok();
2600 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2601 StringRef OptStr = Tok.getString();
2602
2603 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2604 .Case("sy", ARM_MB::SY)
2605 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002606 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002607 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002608 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002609 .Case("ishst", ARM_MB::ISHST)
2610 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002611 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002612 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002613 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002614 .Case("osh", ARM_MB::OSH)
2615 .Case("oshst", ARM_MB::OSHST)
2616 .Default(~0U);
2617
2618 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002619 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002620
2621 Parser.Lex(); // Eat identifier token.
2622 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002623 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002624}
2625
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002626/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002627ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002628parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002629 SMLoc S = Parser.getTok().getLoc();
2630 const AsmToken &Tok = Parser.getTok();
2631 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2632 StringRef IFlagsStr = Tok.getString();
2633
Owen Anderson10c5b122011-10-05 17:16:40 +00002634 // An iflags string of "none" is interpreted to mean that none of the AIF
2635 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002636 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00002637 if (IFlagsStr != "none") {
2638 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2639 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2640 .Case("a", ARM_PROC::A)
2641 .Case("i", ARM_PROC::I)
2642 .Case("f", ARM_PROC::F)
2643 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002644
Owen Anderson10c5b122011-10-05 17:16:40 +00002645 // If some specific iflag is already set, it means that some letter is
2646 // present more than once, this is not acceptable.
2647 if (Flag == ~0U || (IFlags & Flag))
2648 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002649
Owen Anderson10c5b122011-10-05 17:16:40 +00002650 IFlags |= Flag;
2651 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002652 }
2653
2654 Parser.Lex(); // Eat identifier token.
2655 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2656 return MatchOperand_Success;
2657}
2658
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002659/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002660ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002661parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002662 SMLoc S = Parser.getTok().getLoc();
2663 const AsmToken &Tok = Parser.getTok();
2664 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2665 StringRef Mask = Tok.getString();
2666
James Molloy21efa7d2011-09-28 14:21:38 +00002667 if (isMClass()) {
2668 // See ARMv6-M 10.1.1
2669 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2670 .Case("apsr", 0)
2671 .Case("iapsr", 1)
2672 .Case("eapsr", 2)
2673 .Case("xpsr", 3)
2674 .Case("ipsr", 5)
2675 .Case("epsr", 6)
2676 .Case("iepsr", 7)
2677 .Case("msp", 8)
2678 .Case("psp", 9)
2679 .Case("primask", 16)
2680 .Case("basepri", 17)
2681 .Case("basepri_max", 18)
2682 .Case("faultmask", 19)
2683 .Case("control", 20)
2684 .Default(~0U);
2685
2686 if (FlagsVal == ~0U)
2687 return MatchOperand_NoMatch;
2688
2689 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2690 // basepri, basepri_max and faultmask only valid for V7m.
2691 return MatchOperand_NoMatch;
2692
2693 Parser.Lex(); // Eat identifier token.
2694 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2695 return MatchOperand_Success;
2696 }
2697
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002698 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2699 size_t Start = 0, Next = Mask.find('_');
2700 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002701 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002702 if (Next != StringRef::npos)
2703 Flags = Mask.slice(Next+1, Mask.size());
2704
2705 // FlagsVal contains the complete mask:
2706 // 3-0: Mask
2707 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2708 unsigned FlagsVal = 0;
2709
2710 if (SpecReg == "apsr") {
2711 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002712 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002713 .Case("g", 0x4) // same as CPSR_s
2714 .Case("nzcvqg", 0xc) // same as CPSR_fs
2715 .Default(~0U);
2716
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002717 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002718 if (!Flags.empty())
2719 return MatchOperand_NoMatch;
2720 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00002721 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002722 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002723 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00002724 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2725 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002726 for (int i = 0, e = Flags.size(); i != e; ++i) {
2727 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2728 .Case("c", 1)
2729 .Case("x", 2)
2730 .Case("s", 4)
2731 .Case("f", 8)
2732 .Default(~0U);
2733
2734 // If some specific flag is already set, it means that some letter is
2735 // present more than once, this is not acceptable.
2736 if (FlagsVal == ~0U || (FlagsVal & Flag))
2737 return MatchOperand_NoMatch;
2738 FlagsVal |= Flag;
2739 }
2740 } else // No match for special register.
2741 return MatchOperand_NoMatch;
2742
Owen Anderson03a173e2011-10-21 18:43:28 +00002743 // Special register without flags is NOT equivalent to "fc" flags.
2744 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2745 // two lines would enable gas compatibility at the expense of breaking
2746 // round-tripping.
2747 //
2748 // if (!FlagsVal)
2749 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002750
2751 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2752 if (SpecReg == "spsr")
2753 FlagsVal |= 16;
2754
2755 Parser.Lex(); // Eat identifier token.
2756 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2757 return MatchOperand_Success;
2758}
2759
Jim Grosbach27c1e252011-07-21 17:23:04 +00002760ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2761parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2762 int Low, int High) {
2763 const AsmToken &Tok = Parser.getTok();
2764 if (Tok.isNot(AsmToken::Identifier)) {
2765 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2766 return MatchOperand_ParseFail;
2767 }
2768 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002769 std::string LowerOp = Op.lower();
2770 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00002771 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2772 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2773 return MatchOperand_ParseFail;
2774 }
2775 Parser.Lex(); // Eat shift type token.
2776
2777 // There must be a '#' and a shift amount.
2778 if (Parser.getTok().isNot(AsmToken::Hash)) {
2779 Error(Parser.getTok().getLoc(), "'#' expected");
2780 return MatchOperand_ParseFail;
2781 }
2782 Parser.Lex(); // Eat hash token.
2783
2784 const MCExpr *ShiftAmount;
2785 SMLoc Loc = Parser.getTok().getLoc();
2786 if (getParser().ParseExpression(ShiftAmount)) {
2787 Error(Loc, "illegal expression");
2788 return MatchOperand_ParseFail;
2789 }
2790 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2791 if (!CE) {
2792 Error(Loc, "constant expression expected");
2793 return MatchOperand_ParseFail;
2794 }
2795 int Val = CE->getValue();
2796 if (Val < Low || Val > High) {
2797 Error(Loc, "immediate value out of range");
2798 return MatchOperand_ParseFail;
2799 }
2800
2801 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2802
2803 return MatchOperand_Success;
2804}
2805
Jim Grosbach0a547702011-07-22 17:44:50 +00002806ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2807parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2808 const AsmToken &Tok = Parser.getTok();
2809 SMLoc S = Tok.getLoc();
2810 if (Tok.isNot(AsmToken::Identifier)) {
2811 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2812 return MatchOperand_ParseFail;
2813 }
2814 int Val = StringSwitch<int>(Tok.getString())
2815 .Case("be", 1)
2816 .Case("le", 0)
2817 .Default(-1);
2818 Parser.Lex(); // Eat the token.
2819
2820 if (Val == -1) {
2821 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2822 return MatchOperand_ParseFail;
2823 }
2824 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2825 getContext()),
2826 S, Parser.getTok().getLoc()));
2827 return MatchOperand_Success;
2828}
2829
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002830/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2831/// instructions. Legal values are:
2832/// lsl #n 'n' in [0,31]
2833/// asr #n 'n' in [1,32]
2834/// n == 32 encoded as n == 0.
2835ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2836parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2837 const AsmToken &Tok = Parser.getTok();
2838 SMLoc S = Tok.getLoc();
2839 if (Tok.isNot(AsmToken::Identifier)) {
2840 Error(S, "shift operator 'asr' or 'lsl' expected");
2841 return MatchOperand_ParseFail;
2842 }
2843 StringRef ShiftName = Tok.getString();
2844 bool isASR;
2845 if (ShiftName == "lsl" || ShiftName == "LSL")
2846 isASR = false;
2847 else if (ShiftName == "asr" || ShiftName == "ASR")
2848 isASR = true;
2849 else {
2850 Error(S, "shift operator 'asr' or 'lsl' expected");
2851 return MatchOperand_ParseFail;
2852 }
2853 Parser.Lex(); // Eat the operator.
2854
2855 // A '#' and a shift amount.
2856 if (Parser.getTok().isNot(AsmToken::Hash)) {
2857 Error(Parser.getTok().getLoc(), "'#' expected");
2858 return MatchOperand_ParseFail;
2859 }
2860 Parser.Lex(); // Eat hash token.
2861
2862 const MCExpr *ShiftAmount;
2863 SMLoc E = Parser.getTok().getLoc();
2864 if (getParser().ParseExpression(ShiftAmount)) {
2865 Error(E, "malformed shift expression");
2866 return MatchOperand_ParseFail;
2867 }
2868 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2869 if (!CE) {
2870 Error(E, "shift amount must be an immediate");
2871 return MatchOperand_ParseFail;
2872 }
2873
2874 int64_t Val = CE->getValue();
2875 if (isASR) {
2876 // Shift amount must be in [1,32]
2877 if (Val < 1 || Val > 32) {
2878 Error(E, "'asr' shift amount must be in range [1,32]");
2879 return MatchOperand_ParseFail;
2880 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00002881 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2882 if (isThumb() && Val == 32) {
2883 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2884 return MatchOperand_ParseFail;
2885 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002886 if (Val == 32) Val = 0;
2887 } else {
2888 // Shift amount must be in [1,32]
2889 if (Val < 0 || Val > 31) {
2890 Error(E, "'lsr' shift amount must be in range [0,31]");
2891 return MatchOperand_ParseFail;
2892 }
2893 }
2894
2895 E = Parser.getTok().getLoc();
2896 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2897
2898 return MatchOperand_Success;
2899}
2900
Jim Grosbach833b9d32011-07-27 20:15:40 +00002901/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2902/// of instructions. Legal values are:
2903/// ror #n 'n' in {0, 8, 16, 24}
2904ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2905parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2906 const AsmToken &Tok = Parser.getTok();
2907 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00002908 if (Tok.isNot(AsmToken::Identifier))
2909 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002910 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00002911 if (ShiftName != "ror" && ShiftName != "ROR")
2912 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002913 Parser.Lex(); // Eat the operator.
2914
2915 // A '#' and a rotate amount.
2916 if (Parser.getTok().isNot(AsmToken::Hash)) {
2917 Error(Parser.getTok().getLoc(), "'#' expected");
2918 return MatchOperand_ParseFail;
2919 }
2920 Parser.Lex(); // Eat hash token.
2921
2922 const MCExpr *ShiftAmount;
2923 SMLoc E = Parser.getTok().getLoc();
2924 if (getParser().ParseExpression(ShiftAmount)) {
2925 Error(E, "malformed rotate expression");
2926 return MatchOperand_ParseFail;
2927 }
2928 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2929 if (!CE) {
2930 Error(E, "rotate amount must be an immediate");
2931 return MatchOperand_ParseFail;
2932 }
2933
2934 int64_t Val = CE->getValue();
2935 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2936 // normally, zero is represented in asm by omitting the rotate operand
2937 // entirely.
2938 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2939 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2940 return MatchOperand_ParseFail;
2941 }
2942
2943 E = Parser.getTok().getLoc();
2944 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2945
2946 return MatchOperand_Success;
2947}
2948
Jim Grosbach864b6092011-07-28 21:34:26 +00002949ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2950parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2951 SMLoc S = Parser.getTok().getLoc();
2952 // The bitfield descriptor is really two operands, the LSB and the width.
2953 if (Parser.getTok().isNot(AsmToken::Hash)) {
2954 Error(Parser.getTok().getLoc(), "'#' expected");
2955 return MatchOperand_ParseFail;
2956 }
2957 Parser.Lex(); // Eat hash token.
2958
2959 const MCExpr *LSBExpr;
2960 SMLoc E = Parser.getTok().getLoc();
2961 if (getParser().ParseExpression(LSBExpr)) {
2962 Error(E, "malformed immediate expression");
2963 return MatchOperand_ParseFail;
2964 }
2965 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2966 if (!CE) {
2967 Error(E, "'lsb' operand must be an immediate");
2968 return MatchOperand_ParseFail;
2969 }
2970
2971 int64_t LSB = CE->getValue();
2972 // The LSB must be in the range [0,31]
2973 if (LSB < 0 || LSB > 31) {
2974 Error(E, "'lsb' operand must be in the range [0,31]");
2975 return MatchOperand_ParseFail;
2976 }
2977 E = Parser.getTok().getLoc();
2978
2979 // Expect another immediate operand.
2980 if (Parser.getTok().isNot(AsmToken::Comma)) {
2981 Error(Parser.getTok().getLoc(), "too few operands");
2982 return MatchOperand_ParseFail;
2983 }
2984 Parser.Lex(); // Eat hash token.
2985 if (Parser.getTok().isNot(AsmToken::Hash)) {
2986 Error(Parser.getTok().getLoc(), "'#' expected");
2987 return MatchOperand_ParseFail;
2988 }
2989 Parser.Lex(); // Eat hash token.
2990
2991 const MCExpr *WidthExpr;
2992 if (getParser().ParseExpression(WidthExpr)) {
2993 Error(E, "malformed immediate expression");
2994 return MatchOperand_ParseFail;
2995 }
2996 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2997 if (!CE) {
2998 Error(E, "'width' operand must be an immediate");
2999 return MatchOperand_ParseFail;
3000 }
3001
3002 int64_t Width = CE->getValue();
3003 // The LSB must be in the range [1,32-lsb]
3004 if (Width < 1 || Width > 32 - LSB) {
3005 Error(E, "'width' operand must be in the range [1,32-lsb]");
3006 return MatchOperand_ParseFail;
3007 }
3008 E = Parser.getTok().getLoc();
3009
3010 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3011
3012 return MatchOperand_Success;
3013}
3014
Jim Grosbachd3595712011-08-03 23:50:40 +00003015ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3016parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3017 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003018 // postidx_reg := '+' register {, shift}
3019 // | '-' register {, shift}
3020 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003021
3022 // This method must return MatchOperand_NoMatch without consuming any tokens
3023 // in the case where there is no match, as other alternatives take other
3024 // parse methods.
3025 AsmToken Tok = Parser.getTok();
3026 SMLoc S = Tok.getLoc();
3027 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003028 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003029 int Reg = -1;
3030 if (Tok.is(AsmToken::Plus)) {
3031 Parser.Lex(); // Eat the '+' token.
3032 haveEaten = true;
3033 } else if (Tok.is(AsmToken::Minus)) {
3034 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003035 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003036 haveEaten = true;
3037 }
3038 if (Parser.getTok().is(AsmToken::Identifier))
3039 Reg = tryParseRegister();
3040 if (Reg == -1) {
3041 if (!haveEaten)
3042 return MatchOperand_NoMatch;
3043 Error(Parser.getTok().getLoc(), "register expected");
3044 return MatchOperand_ParseFail;
3045 }
3046 SMLoc E = Parser.getTok().getLoc();
3047
Jim Grosbachc320c852011-08-05 21:28:30 +00003048 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3049 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003050 if (Parser.getTok().is(AsmToken::Comma)) {
3051 Parser.Lex(); // Eat the ','.
3052 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3053 return MatchOperand_ParseFail;
3054 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003055
3056 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3057 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003058
3059 return MatchOperand_Success;
3060}
3061
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003062ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3063parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3064 // Check for a post-index addressing register operand. Specifically:
3065 // am3offset := '+' register
3066 // | '-' register
3067 // | register
3068 // | # imm
3069 // | # + imm
3070 // | # - imm
3071
3072 // This method must return MatchOperand_NoMatch without consuming any tokens
3073 // in the case where there is no match, as other alternatives take other
3074 // parse methods.
3075 AsmToken Tok = Parser.getTok();
3076 SMLoc S = Tok.getLoc();
3077
3078 // Do immediates first, as we always parse those if we have a '#'.
3079 if (Parser.getTok().is(AsmToken::Hash)) {
3080 Parser.Lex(); // Eat the '#'.
3081 // Explicitly look for a '-', as we need to encode negative zero
3082 // differently.
3083 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3084 const MCExpr *Offset;
3085 if (getParser().ParseExpression(Offset))
3086 return MatchOperand_ParseFail;
3087 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3088 if (!CE) {
3089 Error(S, "constant expression expected");
3090 return MatchOperand_ParseFail;
3091 }
3092 SMLoc E = Tok.getLoc();
3093 // Negative zero is encoded as the flag value INT32_MIN.
3094 int32_t Val = CE->getValue();
3095 if (isNegative && Val == 0)
3096 Val = INT32_MIN;
3097
3098 Operands.push_back(
3099 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3100
3101 return MatchOperand_Success;
3102 }
3103
3104
3105 bool haveEaten = false;
3106 bool isAdd = true;
3107 int Reg = -1;
3108 if (Tok.is(AsmToken::Plus)) {
3109 Parser.Lex(); // Eat the '+' token.
3110 haveEaten = true;
3111 } else if (Tok.is(AsmToken::Minus)) {
3112 Parser.Lex(); // Eat the '-' token.
3113 isAdd = false;
3114 haveEaten = true;
3115 }
3116 if (Parser.getTok().is(AsmToken::Identifier))
3117 Reg = tryParseRegister();
3118 if (Reg == -1) {
3119 if (!haveEaten)
3120 return MatchOperand_NoMatch;
3121 Error(Parser.getTok().getLoc(), "register expected");
3122 return MatchOperand_ParseFail;
3123 }
3124 SMLoc E = Parser.getTok().getLoc();
3125
3126 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3127 0, S, E));
3128
3129 return MatchOperand_Success;
3130}
3131
Jim Grosbach7db8d692011-09-08 22:07:06 +00003132/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3133/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3134/// when they refer multiple MIOperands inside a single one.
3135bool ARMAsmParser::
3136cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3137 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3138 // Rt, Rt2
3139 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3140 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3141 // Create a writeback register dummy placeholder.
3142 Inst.addOperand(MCOperand::CreateReg(0));
3143 // addr
3144 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3145 // pred
3146 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3147 return true;
3148}
3149
3150/// cvtT2StrdPre - Convert parsed operands to MCInst.
3151/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3152/// when they refer multiple MIOperands inside a single one.
3153bool ARMAsmParser::
3154cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3155 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3156 // Create a writeback register dummy placeholder.
3157 Inst.addOperand(MCOperand::CreateReg(0));
3158 // Rt, Rt2
3159 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3160 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3161 // addr
3162 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3163 // pred
3164 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3165 return true;
3166}
3167
Jim Grosbachc086f682011-09-08 00:39:19 +00003168/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3169/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3170/// when they refer multiple MIOperands inside a single one.
3171bool ARMAsmParser::
3172cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3173 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3174 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3175
3176 // Create a writeback register dummy placeholder.
3177 Inst.addOperand(MCOperand::CreateImm(0));
3178
3179 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3180 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3181 return true;
3182}
3183
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003184/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3185/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3186/// when they refer multiple MIOperands inside a single one.
3187bool ARMAsmParser::
3188cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3189 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3190 // Create a writeback register dummy placeholder.
3191 Inst.addOperand(MCOperand::CreateImm(0));
3192 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3193 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3194 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3195 return true;
3196}
3197
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003198/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003199/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3200/// when they refer multiple MIOperands inside a single one.
3201bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003202cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003203 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3204 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3205
3206 // Create a writeback register dummy placeholder.
3207 Inst.addOperand(MCOperand::CreateImm(0));
3208
Jim Grosbachd3595712011-08-03 23:50:40 +00003209 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003210 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3211 return true;
3212}
3213
Owen Anderson16d33f32011-08-26 20:43:14 +00003214/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3215/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3216/// when they refer multiple MIOperands inside a single one.
3217bool ARMAsmParser::
3218cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3219 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3220 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3221
3222 // Create a writeback register dummy placeholder.
3223 Inst.addOperand(MCOperand::CreateImm(0));
3224
3225 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3226 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3227 return true;
3228}
3229
3230
Jim Grosbachd564bf32011-08-11 19:22:40 +00003231/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3232/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3233/// when they refer multiple MIOperands inside a single one.
3234bool ARMAsmParser::
3235cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3236 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3237 // Create a writeback register dummy placeholder.
3238 Inst.addOperand(MCOperand::CreateImm(0));
3239 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3240 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3241 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3242 return true;
3243}
3244
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003245/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003246/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3247/// when they refer multiple MIOperands inside a single one.
3248bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003249cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003250 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3251 // Create a writeback register dummy placeholder.
3252 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003253 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3254 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3255 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003256 return true;
3257}
3258
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003259/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3260/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3261/// when they refer multiple MIOperands inside a single one.
3262bool ARMAsmParser::
3263cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3264 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3265 // Create a writeback register dummy placeholder.
3266 Inst.addOperand(MCOperand::CreateImm(0));
3267 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3268 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3269 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3270 return true;
3271}
3272
Jim Grosbachd3595712011-08-03 23:50:40 +00003273/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3274/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3275/// when they refer multiple MIOperands inside a single one.
3276bool ARMAsmParser::
3277cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3278 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3279 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003280 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003281 // Create a writeback register dummy placeholder.
3282 Inst.addOperand(MCOperand::CreateImm(0));
3283 // addr
3284 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3285 // offset
3286 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3287 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003288 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3289 return true;
3290}
3291
Jim Grosbachd3595712011-08-03 23:50:40 +00003292/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003293/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3294/// when they refer multiple MIOperands inside a single one.
3295bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003296cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3297 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3298 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003299 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003300 // Create a writeback register dummy placeholder.
3301 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003302 // addr
3303 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3304 // offset
3305 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3306 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003307 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3308 return true;
3309}
3310
Jim Grosbachd3595712011-08-03 23:50:40 +00003311/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003312/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3313/// when they refer multiple MIOperands inside a single one.
3314bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003315cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3316 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003317 // Create a writeback register dummy placeholder.
3318 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003319 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003320 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003321 // addr
3322 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3323 // offset
3324 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3325 // pred
3326 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3327 return true;
3328}
3329
3330/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3331/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3332/// when they refer multiple MIOperands inside a single one.
3333bool ARMAsmParser::
3334cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3335 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3336 // Create a writeback register dummy placeholder.
3337 Inst.addOperand(MCOperand::CreateImm(0));
3338 // Rt
3339 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3340 // addr
3341 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3342 // offset
3343 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3344 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003345 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3346 return true;
3347}
3348
Jim Grosbach5b96b802011-08-10 20:29:19 +00003349/// cvtLdrdPre - Convert parsed operands to MCInst.
3350/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3351/// when they refer multiple MIOperands inside a single one.
3352bool ARMAsmParser::
3353cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3354 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3355 // Rt, Rt2
3356 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3357 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3358 // Create a writeback register dummy placeholder.
3359 Inst.addOperand(MCOperand::CreateImm(0));
3360 // addr
3361 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3362 // pred
3363 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3364 return true;
3365}
3366
Jim Grosbacheb09f492011-08-11 20:28:23 +00003367/// cvtStrdPre - Convert parsed operands to MCInst.
3368/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3369/// when they refer multiple MIOperands inside a single one.
3370bool ARMAsmParser::
3371cvtStrdPre(MCInst &Inst, unsigned Opcode,
3372 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3373 // Create a writeback register dummy placeholder.
3374 Inst.addOperand(MCOperand::CreateImm(0));
3375 // Rt, Rt2
3376 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3377 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3378 // addr
3379 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3380 // pred
3381 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3382 return true;
3383}
3384
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003385/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3386/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3387/// when they refer multiple MIOperands inside a single one.
3388bool ARMAsmParser::
3389cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3390 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3391 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3392 // Create a writeback register dummy placeholder.
3393 Inst.addOperand(MCOperand::CreateImm(0));
3394 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3395 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3396 return true;
3397}
3398
Jim Grosbach8e048492011-08-19 22:07:46 +00003399/// cvtThumbMultiple- Convert parsed operands to MCInst.
3400/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3401/// when they refer multiple MIOperands inside a single one.
3402bool ARMAsmParser::
3403cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3404 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3405 // The second source operand must be the same register as the destination
3406 // operand.
3407 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003408 (((ARMOperand*)Operands[3])->getReg() !=
3409 ((ARMOperand*)Operands[5])->getReg()) &&
3410 (((ARMOperand*)Operands[3])->getReg() !=
3411 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003412 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003413 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003414 return false;
3415 }
3416 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3417 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3418 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach459422d2011-08-19 22:30:46 +00003419 // If we have a three-operand form, use that, else the second source operand
3420 // is just the destination operand again.
3421 if (Operands.size() == 6)
3422 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3423 else
3424 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003425 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3426
3427 return true;
3428}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003429
Jim Grosbach3ea06572011-10-24 22:16:58 +00003430bool ARMAsmParser::
3431cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3432 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3433 // Vd
3434 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3435 // Create a writeback register dummy placeholder.
3436 Inst.addOperand(MCOperand::CreateImm(0));
3437 // Vn
3438 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3439 // pred
3440 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3441 return true;
3442}
3443
3444bool ARMAsmParser::
3445cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3446 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3447 // Vd
3448 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3449 // Create a writeback register dummy placeholder.
3450 Inst.addOperand(MCOperand::CreateImm(0));
3451 // Vn
3452 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3453 // Vm
3454 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3455 // pred
3456 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3457 return true;
3458}
3459
Jim Grosbach05df4602011-10-31 21:50:31 +00003460bool ARMAsmParser::
3461cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3462 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3463 // Create a writeback register dummy placeholder.
3464 Inst.addOperand(MCOperand::CreateImm(0));
3465 // Vn
3466 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3467 // Vt
3468 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3469 // pred
3470 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3471 return true;
3472}
3473
3474bool ARMAsmParser::
3475cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3476 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3477 // Create a writeback register dummy placeholder.
3478 Inst.addOperand(MCOperand::CreateImm(0));
3479 // Vn
3480 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3481 // Vm
3482 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3483 // Vt
3484 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3485 // pred
3486 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3487 return true;
3488}
3489
Bill Wendlinge18980a2010-11-06 22:36:58 +00003490/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003491/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003492bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003493parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003494 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003495 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003496 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003497 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003498 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003499
Sean Callanan936b0d32010-01-19 21:44:56 +00003500 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003501 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003502 if (BaseRegNum == -1)
3503 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003504
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003505 // The next token must either be a comma or a closing bracket.
3506 const AsmToken &Tok = Parser.getTok();
3507 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003508 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003509
Jim Grosbachd3595712011-08-03 23:50:40 +00003510 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003511 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003512 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003513
Jim Grosbachd3595712011-08-03 23:50:40 +00003514 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003515 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003516
Jim Grosbach40700e02011-09-19 18:42:21 +00003517 // If there's a pre-indexing writeback marker, '!', just add it as a token
3518 // operand. It's rather odd, but syntactically valid.
3519 if (Parser.getTok().is(AsmToken::Exclaim)) {
3520 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3521 Parser.Lex(); // Eat the '!'.
3522 }
3523
Jim Grosbachd3595712011-08-03 23:50:40 +00003524 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003525 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003526
Jim Grosbachd3595712011-08-03 23:50:40 +00003527 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3528 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003529
Jim Grosbacha95ec992011-10-11 17:29:55 +00003530 // If we have a ':', it's an alignment specifier.
3531 if (Parser.getTok().is(AsmToken::Colon)) {
3532 Parser.Lex(); // Eat the ':'.
3533 E = Parser.getTok().getLoc();
3534
3535 const MCExpr *Expr;
3536 if (getParser().ParseExpression(Expr))
3537 return true;
3538
3539 // The expression has to be a constant. Memory references with relocations
3540 // don't come through here, as they use the <label> forms of the relevant
3541 // instructions.
3542 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3543 if (!CE)
3544 return Error (E, "constant expression expected");
3545
3546 unsigned Align = 0;
3547 switch (CE->getValue()) {
3548 default:
3549 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3550 case 64: Align = 8; break;
3551 case 128: Align = 16; break;
3552 case 256: Align = 32; break;
3553 }
3554
3555 // Now we should have the closing ']'
3556 E = Parser.getTok().getLoc();
3557 if (Parser.getTok().isNot(AsmToken::RBrac))
3558 return Error(E, "']' expected");
3559 Parser.Lex(); // Eat right bracket token.
3560
3561 // Don't worry about range checking the value here. That's handled by
3562 // the is*() predicates.
3563 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3564 ARM_AM::no_shift, 0, Align,
3565 false, S, E));
3566
3567 // If there's a pre-indexing writeback marker, '!', just add it as a token
3568 // operand.
3569 if (Parser.getTok().is(AsmToken::Exclaim)) {
3570 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3571 Parser.Lex(); // Eat the '!'.
3572 }
3573
3574 return false;
3575 }
3576
3577 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbachd3595712011-08-03 23:50:40 +00003578 // offset.
3579 if (Parser.getTok().is(AsmToken::Hash)) {
3580 Parser.Lex(); // Eat the '#'.
3581 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003582
Owen Anderson967674d2011-08-29 19:36:44 +00003583 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003584 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003585 if (getParser().ParseExpression(Offset))
3586 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003587
3588 // The expression has to be a constant. Memory references with relocations
3589 // don't come through here, as they use the <label> forms of the relevant
3590 // instructions.
3591 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3592 if (!CE)
3593 return Error (E, "constant expression expected");
3594
Owen Anderson967674d2011-08-29 19:36:44 +00003595 // If the constant was #-0, represent it as INT32_MIN.
3596 int32_t Val = CE->getValue();
3597 if (isNegative && Val == 0)
3598 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3599
Jim Grosbachd3595712011-08-03 23:50:40 +00003600 // Now we should have the closing ']'
3601 E = Parser.getTok().getLoc();
3602 if (Parser.getTok().isNot(AsmToken::RBrac))
3603 return Error(E, "']' expected");
3604 Parser.Lex(); // Eat right bracket token.
3605
3606 // Don't worry about range checking the value here. That's handled by
3607 // the is*() predicates.
3608 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003609 ARM_AM::no_shift, 0, 0,
3610 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003611
3612 // If there's a pre-indexing writeback marker, '!', just add it as a token
3613 // operand.
3614 if (Parser.getTok().is(AsmToken::Exclaim)) {
3615 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3616 Parser.Lex(); // Eat the '!'.
3617 }
3618
3619 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003620 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003621
3622 // The register offset is optionally preceded by a '+' or '-'
3623 bool isNegative = false;
3624 if (Parser.getTok().is(AsmToken::Minus)) {
3625 isNegative = true;
3626 Parser.Lex(); // Eat the '-'.
3627 } else if (Parser.getTok().is(AsmToken::Plus)) {
3628 // Nothing to do.
3629 Parser.Lex(); // Eat the '+'.
3630 }
3631
3632 E = Parser.getTok().getLoc();
3633 int OffsetRegNum = tryParseRegister();
3634 if (OffsetRegNum == -1)
3635 return Error(E, "register expected");
3636
3637 // If there's a shift operator, handle it.
3638 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003639 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00003640 if (Parser.getTok().is(AsmToken::Comma)) {
3641 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003642 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00003643 return true;
3644 }
3645
3646 // Now we should have the closing ']'
3647 E = Parser.getTok().getLoc();
3648 if (Parser.getTok().isNot(AsmToken::RBrac))
3649 return Error(E, "']' expected");
3650 Parser.Lex(); // Eat right bracket token.
3651
3652 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003653 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00003654 S, E));
3655
Jim Grosbachc320c852011-08-05 21:28:30 +00003656 // If there's a pre-indexing writeback marker, '!', just add it as a token
3657 // operand.
3658 if (Parser.getTok().is(AsmToken::Exclaim)) {
3659 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3660 Parser.Lex(); // Eat the '!'.
3661 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003662
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003663 return false;
3664}
3665
Jim Grosbachd3595712011-08-03 23:50:40 +00003666/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003667/// ( lsl | lsr | asr | ror ) , # shift_amount
3668/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00003669/// return true if it parses a shift otherwise it returns false.
3670bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3671 unsigned &Amount) {
3672 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00003673 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003674 if (Tok.isNot(AsmToken::Identifier))
3675 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00003676 StringRef ShiftName = Tok.getString();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003677 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003678 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003679 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003680 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003681 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003682 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003683 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003684 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003685 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003686 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003687 else
Jim Grosbachd3595712011-08-03 23:50:40 +00003688 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00003689 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003690
Jim Grosbachd3595712011-08-03 23:50:40 +00003691 // rrx stands alone.
3692 Amount = 0;
3693 if (St != ARM_AM::rrx) {
3694 Loc = Parser.getTok().getLoc();
3695 // A '#' and a shift amount.
3696 const AsmToken &HashTok = Parser.getTok();
3697 if (HashTok.isNot(AsmToken::Hash))
3698 return Error(HashTok.getLoc(), "'#' expected");
3699 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003700
Jim Grosbachd3595712011-08-03 23:50:40 +00003701 const MCExpr *Expr;
3702 if (getParser().ParseExpression(Expr))
3703 return true;
3704 // Range check the immediate.
3705 // lsl, ror: 0 <= imm <= 31
3706 // lsr, asr: 0 <= imm <= 32
3707 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3708 if (!CE)
3709 return Error(Loc, "shift amount must be an immediate");
3710 int64_t Imm = CE->getValue();
3711 if (Imm < 0 ||
3712 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3713 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3714 return Error(Loc, "immediate shift value out of range");
3715 Amount = Imm;
3716 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003717
3718 return false;
3719}
3720
Jim Grosbache7fbce72011-10-03 23:38:36 +00003721/// parseFPImm - A floating point immediate expression operand.
3722ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3723parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3724 SMLoc S = Parser.getTok().getLoc();
3725
3726 if (Parser.getTok().isNot(AsmToken::Hash))
3727 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00003728
3729 // Disambiguate the VMOV forms that can accept an FP immediate.
3730 // vmov.f32 <sreg>, #imm
3731 // vmov.f64 <dreg>, #imm
3732 // vmov.f32 <dreg>, #imm @ vector f32x2
3733 // vmov.f32 <qreg>, #imm @ vector f32x4
3734 //
3735 // There are also the NEON VMOV instructions which expect an
3736 // integer constant. Make sure we don't try to parse an FPImm
3737 // for these:
3738 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3739 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3740 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3741 TyOp->getToken() != ".f64"))
3742 return MatchOperand_NoMatch;
3743
Jim Grosbache7fbce72011-10-03 23:38:36 +00003744 Parser.Lex(); // Eat the '#'.
3745
3746 // Handle negation, as that still comes through as a separate token.
3747 bool isNegative = false;
3748 if (Parser.getTok().is(AsmToken::Minus)) {
3749 isNegative = true;
3750 Parser.Lex();
3751 }
3752 const AsmToken &Tok = Parser.getTok();
3753 if (Tok.is(AsmToken::Real)) {
3754 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3755 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3756 // If we had a '-' in front, toggle the sign bit.
3757 IntVal ^= (uint64_t)isNegative << 63;
3758 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3759 Parser.Lex(); // Eat the token.
3760 if (Val == -1) {
3761 TokError("floating point value out of range");
3762 return MatchOperand_ParseFail;
3763 }
3764 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3765 return MatchOperand_Success;
3766 }
3767 if (Tok.is(AsmToken::Integer)) {
3768 int64_t Val = Tok.getIntVal();
3769 Parser.Lex(); // Eat the token.
3770 if (Val > 255 || Val < 0) {
3771 TokError("encoded floating point value out of range");
3772 return MatchOperand_ParseFail;
3773 }
3774 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3775 return MatchOperand_Success;
3776 }
3777
3778 TokError("invalid floating point immediate");
3779 return MatchOperand_ParseFail;
3780}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003781/// Parse a arm instruction operand. For now this parses the operand regardless
3782/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003783bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003784 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003785 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003786
3787 // Check if the current operand has a custom associated parser, if so, try to
3788 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003789 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3790 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003791 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00003792 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3793 // there was a match, but an error occurred, in which case, just return that
3794 // the operand parsing failed.
3795 if (ResTy == MatchOperand_ParseFail)
3796 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003797
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003798 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003799 default:
3800 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00003801 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003802 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003803 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003804 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00003805 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00003806 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00003807 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003808 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003809 else if (Res == -1) // irrecoverable error
3810 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003811 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3812 S = Parser.getTok().getLoc();
3813 Parser.Lex();
3814 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3815 return false;
3816 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003817
3818 // Fall though for the Identifier case that is not a register or a
3819 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00003820 }
Jim Grosbach4e380352011-10-26 21:14:08 +00003821 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00003822 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00003823 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00003824 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00003825 // This was not a register so parse other operands that start with an
3826 // identifier (like labels) as expressions and create them as immediates.
3827 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003828 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00003829 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003830 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003831 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003832 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3833 return false;
3834 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003835 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003836 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00003837 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003838 return parseRegisterList(Operands);
Owen Andersonf02d98d2011-08-29 17:17:09 +00003839 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00003840 // #42 -> immediate.
3841 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003842 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003843 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00003844 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00003845 const MCExpr *ImmVal;
3846 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003847 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003848 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00003849 if (CE) {
3850 int32_t Val = CE->getValue();
3851 if (isNegative && Val == 0)
3852 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00003853 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003854 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003855 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3856 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003857 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003858 case AsmToken::Colon: {
3859 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00003860 // FIXME: Check it's an expression prefix,
3861 // e.g. (FOO - :lower16:BAR) isn't legal.
3862 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003863 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003864 return true;
3865
Evan Cheng965b3c72011-01-13 07:58:56 +00003866 const MCExpr *SubExprVal;
3867 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003868 return true;
3869
Evan Cheng965b3c72011-01-13 07:58:56 +00003870 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3871 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00003872 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00003873 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00003874 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003875 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003876 }
3877}
3878
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003879// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00003880// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003881bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00003882 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003883
3884 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00003885 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00003886 Parser.Lex(); // Eat ':'
3887
3888 if (getLexer().isNot(AsmToken::Identifier)) {
3889 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3890 return true;
3891 }
3892
3893 StringRef IDVal = Parser.getTok().getIdentifier();
3894 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003895 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003896 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003897 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003898 } else {
3899 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3900 return true;
3901 }
3902 Parser.Lex();
3903
3904 if (getLexer().isNot(AsmToken::Colon)) {
3905 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3906 return true;
3907 }
3908 Parser.Lex(); // Eat the last ':'
3909 return false;
3910}
3911
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003912/// \brief Given a mnemonic, split out possible predication code and carry
3913/// setting letters to form a canonical mnemonic and flags.
3914//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003915// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003916// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003917StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003918 unsigned &PredicationCode,
3919 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003920 unsigned &ProcessorIMod,
3921 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003922 PredicationCode = ARMCC::AL;
3923 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003924 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003925
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003926 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003927 //
3928 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003929 if ((Mnemonic == "movs" && isThumb()) ||
3930 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3931 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3932 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3933 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3934 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3935 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3936 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003937 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003938
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003939 // First, split out any predication code. Ignore mnemonics we know aren't
3940 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00003941 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00003942 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00003943 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00003944 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003945 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3946 .Case("eq", ARMCC::EQ)
3947 .Case("ne", ARMCC::NE)
3948 .Case("hs", ARMCC::HS)
3949 .Case("cs", ARMCC::HS)
3950 .Case("lo", ARMCC::LO)
3951 .Case("cc", ARMCC::LO)
3952 .Case("mi", ARMCC::MI)
3953 .Case("pl", ARMCC::PL)
3954 .Case("vs", ARMCC::VS)
3955 .Case("vc", ARMCC::VC)
3956 .Case("hi", ARMCC::HI)
3957 .Case("ls", ARMCC::LS)
3958 .Case("ge", ARMCC::GE)
3959 .Case("lt", ARMCC::LT)
3960 .Case("gt", ARMCC::GT)
3961 .Case("le", ARMCC::LE)
3962 .Case("al", ARMCC::AL)
3963 .Default(~0U);
3964 if (CC != ~0U) {
3965 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3966 PredicationCode = CC;
3967 }
Bill Wendling193961b2010-10-29 23:50:21 +00003968 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003969
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003970 // Next, determine if we have a carry setting bit. We explicitly ignore all
3971 // the instructions we know end in 's'.
3972 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00003973 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003974 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3975 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3976 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00003977 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3978 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003979 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3980 CarrySetting = true;
3981 }
3982
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003983 // The "cps" instruction can have a interrupt mode operand which is glued into
3984 // the mnemonic. Check if this is the case, split it and parse the imod op
3985 if (Mnemonic.startswith("cps")) {
3986 // Split out any imod code.
3987 unsigned IMod =
3988 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3989 .Case("ie", ARM_PROC::IE)
3990 .Case("id", ARM_PROC::ID)
3991 .Default(~0U);
3992 if (IMod != ~0U) {
3993 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3994 ProcessorIMod = IMod;
3995 }
3996 }
3997
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003998 // The "it" instruction has the condition mask on the end of the mnemonic.
3999 if (Mnemonic.startswith("it")) {
4000 ITMask = Mnemonic.slice(2, Mnemonic.size());
4001 Mnemonic = Mnemonic.slice(0, 2);
4002 }
4003
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004004 return Mnemonic;
4005}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004006
4007/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4008/// inclusion of carry set or predication code operands.
4009//
4010// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004011void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004012getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004013 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004014 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4015 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004016 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004017 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004018 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004019 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004020 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004021 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004022 Mnemonic == "mla" || Mnemonic == "smlal" ||
4023 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004024 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004025 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004026 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004027
Daniel Dunbar09264122011-01-11 19:06:29 +00004028 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4029 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4030 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4031 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004032 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4033 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004034 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004035 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4036 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4037 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004038 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4039 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004040 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004041 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004042 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004043 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004044
Jim Grosbach6c45b752011-09-16 16:39:25 +00004045 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004046 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004047 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004048 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004049 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004050}
4051
Jim Grosbach7283da92011-08-16 21:12:37 +00004052bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4053 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004054 // FIXME: This is all horribly hacky. We really need a better way to deal
4055 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004056
4057 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4058 // another does not. Specifically, the MOVW instruction does not. So we
4059 // special case it here and remove the defaulted (non-setting) cc_out
4060 // operand if that's the instruction we're trying to match.
4061 //
4062 // We do this as post-processing of the explicit operands rather than just
4063 // conditionally adding the cc_out in the first place because we need
4064 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004065 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004066 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4067 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4068 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4069 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004070
4071 // Register-register 'add' for thumb does not have a cc_out operand
4072 // when there are only two register operands.
4073 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4074 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4075 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4076 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4077 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004078 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004079 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4080 // have to check the immediate range here since Thumb2 has a variant
4081 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004082 if (((isThumb() && Mnemonic == "add") ||
4083 (isThumbTwo() && Mnemonic == "sub")) &&
4084 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004085 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4086 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4087 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004088 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4089 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4090 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004091 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004092 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4093 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004094 // selecting via the generic "add" mnemonic, so to know that we
4095 // should remove the cc_out operand, we have to explicitly check that
4096 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004097 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4098 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004099 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4100 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4101 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4102 // Nest conditions rather than one big 'if' statement for readability.
4103 //
4104 // If either register is a high reg, it's either one of the SP
4105 // variants (handled above) or a 32-bit encoding, so we just
4106 // check against T3.
4107 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4108 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4109 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4110 return false;
4111 // If both registers are low, we're in an IT block, and the immediate is
4112 // in range, we should use encoding T1 instead, which has a cc_out.
4113 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004114 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004115 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4116 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4117 return false;
4118
4119 // Otherwise, we use encoding T4, which does not have a cc_out
4120 // operand.
4121 return true;
4122 }
4123
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004124 // The thumb2 multiply instruction doesn't have a CCOut register, so
4125 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4126 // use the 16-bit encoding or not.
4127 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4128 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4129 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4130 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4131 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4132 // If the registers aren't low regs, the destination reg isn't the
4133 // same as one of the source regs, or the cc_out operand is zero
4134 // outside of an IT block, we have to use the 32-bit encoding, so
4135 // remove the cc_out operand.
4136 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4137 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4138 !inITBlock() ||
4139 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4140 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4141 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4142 static_cast<ARMOperand*>(Operands[4])->getReg())))
4143 return true;
4144
4145
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004146
Jim Grosbach4b701af2011-08-24 21:42:27 +00004147 // Register-register 'add/sub' for thumb does not have a cc_out operand
4148 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4149 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4150 // right, this will result in better diagnostics (which operand is off)
4151 // anyway.
4152 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4153 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004154 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4155 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4156 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4157 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004158
Jim Grosbach7283da92011-08-16 21:12:37 +00004159 return false;
4160}
4161
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004162/// Parse an arm instruction mnemonic followed by its operands.
4163bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4164 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4165 // Create the leading tokens for the mnemonic, split by '.' characters.
4166 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004167 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004168
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004169 // Split out the predication code and carry setting flag from the mnemonic.
4170 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004171 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004172 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004173 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004174 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004175 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004176
Jim Grosbach1c171b12011-08-25 17:23:55 +00004177 // In Thumb1, only the branch (B) instruction can be predicated.
4178 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4179 Parser.EatToEndOfStatement();
4180 return Error(NameLoc, "conditional execution not supported in Thumb1");
4181 }
4182
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004183 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4184
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004185 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4186 // is the mask as it will be for the IT encoding if the conditional
4187 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4188 // where the conditional bit0 is zero, the instruction post-processing
4189 // will adjust the mask accordingly.
4190 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004191 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4192 if (ITMask.size() > 3) {
4193 Parser.EatToEndOfStatement();
4194 return Error(Loc, "too many conditions on IT instruction");
4195 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004196 unsigned Mask = 8;
4197 for (unsigned i = ITMask.size(); i != 0; --i) {
4198 char pos = ITMask[i - 1];
4199 if (pos != 't' && pos != 'e') {
4200 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004201 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004202 }
4203 Mask >>= 1;
4204 if (ITMask[i - 1] == 't')
4205 Mask |= 8;
4206 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004207 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004208 }
4209
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004210 // FIXME: This is all a pretty gross hack. We should automatically handle
4211 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004212
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004213 // Next, add the CCOut and ConditionCode operands, if needed.
4214 //
4215 // For mnemonics which can ever incorporate a carry setting bit or predication
4216 // code, our matching model involves us always generating CCOut and
4217 // ConditionCode operands to match the mnemonic "as written" and then we let
4218 // the matcher deal with finding the right instruction or generating an
4219 // appropriate error.
4220 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004221 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004222
Jim Grosbach03a8a162011-07-14 22:04:21 +00004223 // If we had a carry-set on an instruction that can't do that, issue an
4224 // error.
4225 if (!CanAcceptCarrySet && CarrySetting) {
4226 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004227 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004228 "' can not set flags, but 's' suffix specified");
4229 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004230 // If we had a predication code on an instruction that can't do that, issue an
4231 // error.
4232 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4233 Parser.EatToEndOfStatement();
4234 return Error(NameLoc, "instruction '" + Mnemonic +
4235 "' is not predicable, but condition code specified");
4236 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004237
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004238 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004239 if (CanAcceptCarrySet) {
4240 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004241 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004242 Loc));
4243 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004244
4245 // Add the predication code operand, if necessary.
4246 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004247 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4248 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004249 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004250 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004251 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004252
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004253 // Add the processor imod operand, if necessary.
4254 if (ProcessorIMod) {
4255 Operands.push_back(ARMOperand::CreateImm(
4256 MCConstantExpr::Create(ProcessorIMod, getContext()),
4257 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004258 }
4259
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004260 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004261 while (Next != StringRef::npos) {
4262 Start = Next;
4263 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004264 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004265
Jim Grosbach838ed3a2011-08-24 22:19:48 +00004266 // For now, we're only parsing Thumb1 (for the most part), so
4267 // just ignore ".n" qualifiers. We'll use them to restrict
4268 // matching when we do Thumb2.
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004269 if (ExtraToken != ".n") {
4270 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4271 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4272 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004273 }
4274
4275 // Read the remaining operands.
4276 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004277 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004278 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004279 Parser.EatToEndOfStatement();
4280 return true;
4281 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004282
4283 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004284 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004285
4286 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004287 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004288 Parser.EatToEndOfStatement();
4289 return true;
4290 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004291 }
4292 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004293
Chris Lattnera2a9d162010-09-11 16:18:25 +00004294 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004295 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004296 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004297 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004298 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004299
Chris Lattner91689c12010-09-08 05:10:46 +00004300 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004301
Jim Grosbach7283da92011-08-16 21:12:37 +00004302 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4303 // do and don't have a cc_out optional-def operand. With some spot-checks
4304 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004305 // parse and adjust accordingly before actually matching. We shouldn't ever
4306 // try to remove a cc_out operand that was explicitly set on the the
4307 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4308 // table driven matcher doesn't fit well with the ARM instruction set.
4309 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004310 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4311 Operands.erase(Operands.begin() + 1);
4312 delete Op;
4313 }
4314
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004315 // ARM mode 'blx' need special handling, as the register operand version
4316 // is predicable, but the label operand version is not. So, we can't rely
4317 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004318 // a k_CondCode operand in the list. If we're trying to match the label
4319 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004320 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4321 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4322 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4323 Operands.erase(Operands.begin() + 1);
4324 delete Op;
4325 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004326
4327 // The vector-compare-to-zero instructions have a literal token "#0" at
4328 // the end that comes to here as an immediate operand. Convert it to a
4329 // token to play nicely with the matcher.
4330 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4331 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4332 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4333 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4334 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4335 if (CE && CE->getValue() == 0) {
4336 Operands.erase(Operands.begin() + 5);
4337 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4338 delete Op;
4339 }
4340 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004341 // VCMP{E} does the same thing, but with a different operand count.
4342 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4343 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4344 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4345 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4346 if (CE && CE->getValue() == 0) {
4347 Operands.erase(Operands.begin() + 4);
4348 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4349 delete Op;
4350 }
4351 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004352 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4353 // end. Convert it to a token here.
4354 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4355 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4356 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4357 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4358 if (CE && CE->getValue() == 0) {
4359 Operands.erase(Operands.begin() + 5);
4360 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4361 delete Op;
4362 }
4363 }
4364
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004365 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004366}
4367
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004368// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004369
4370// return 'true' if register list contains non-low GPR registers,
4371// 'false' otherwise. If Reg is in the register list or is HiReg, set
4372// 'containsReg' to true.
4373static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4374 unsigned HiReg, bool &containsReg) {
4375 containsReg = false;
4376 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4377 unsigned OpReg = Inst.getOperand(i).getReg();
4378 if (OpReg == Reg)
4379 containsReg = true;
4380 // Anything other than a low register isn't legal here.
4381 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4382 return true;
4383 }
4384 return false;
4385}
4386
Jim Grosbacha31f2232011-09-07 18:05:34 +00004387// Check if the specified regisgter is in the register list of the inst,
4388// starting at the indicated operand number.
4389static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4390 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4391 unsigned OpReg = Inst.getOperand(i).getReg();
4392 if (OpReg == Reg)
4393 return true;
4394 }
4395 return false;
4396}
4397
Jim Grosbached16ec42011-08-29 22:24:09 +00004398// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4399// the ARMInsts array) instead. Getting that here requires awkward
4400// API changes, though. Better way?
4401namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004402extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004403}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004404static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004405 return ARMInsts[Opcode];
4406}
4407
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004408// FIXME: We would really like to be able to tablegen'erate this.
4409bool ARMAsmParser::
4410validateInstruction(MCInst &Inst,
4411 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004412 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004413 SMLoc Loc = Operands[0]->getStartLoc();
4414 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004415 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4416 // being allowed in IT blocks, but not being predicable. It just always
4417 // executes.
4418 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004419 unsigned bit = 1;
4420 if (ITState.FirstCond)
4421 ITState.FirstCond = false;
4422 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004423 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004424 // The instruction must be predicable.
4425 if (!MCID.isPredicable())
4426 return Error(Loc, "instructions in IT block must be predicable");
4427 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4428 unsigned ITCond = bit ? ITState.Cond :
4429 ARMCC::getOppositeCondition(ITState.Cond);
4430 if (Cond != ITCond) {
4431 // Find the condition code Operand to get its SMLoc information.
4432 SMLoc CondLoc;
4433 for (unsigned i = 1; i < Operands.size(); ++i)
4434 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4435 CondLoc = Operands[i]->getStartLoc();
4436 return Error(CondLoc, "incorrect condition in IT block; got '" +
4437 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4438 "', but expected '" +
4439 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4440 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004441 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004442 } else if (isThumbTwo() && MCID.isPredicable() &&
4443 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004444 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4445 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004446 return Error(Loc, "predicated instructions must be in IT block");
4447
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004448 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004449 case ARM::LDRD:
4450 case ARM::LDRD_PRE:
4451 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004452 case ARM::LDREXD: {
4453 // Rt2 must be Rt + 1.
4454 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4455 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4456 if (Rt2 != Rt + 1)
4457 return Error(Operands[3]->getStartLoc(),
4458 "destination operands must be sequential");
4459 return false;
4460 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00004461 case ARM::STRD: {
4462 // Rt2 must be Rt + 1.
4463 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4464 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4465 if (Rt2 != Rt + 1)
4466 return Error(Operands[3]->getStartLoc(),
4467 "source operands must be sequential");
4468 return false;
4469 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00004470 case ARM::STRD_PRE:
4471 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004472 case ARM::STREXD: {
4473 // Rt2 must be Rt + 1.
4474 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4475 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4476 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00004477 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004478 "source operands must be sequential");
4479 return false;
4480 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00004481 case ARM::SBFX:
4482 case ARM::UBFX: {
4483 // width must be in range [1, 32-lsb]
4484 unsigned lsb = Inst.getOperand(2).getImm();
4485 unsigned widthm1 = Inst.getOperand(3).getImm();
4486 if (widthm1 >= 32 - lsb)
4487 return Error(Operands[5]->getStartLoc(),
4488 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00004489 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00004490 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00004491 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00004492 // If we're parsing Thumb2, the .w variant is available and handles
4493 // most cases that are normally illegal for a Thumb1 LDM
4494 // instruction. We'll make the transformation in processInstruction()
4495 // if necessary.
4496 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00004497 // Thumb LDM instructions are writeback iff the base register is not
4498 // in the register list.
4499 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00004500 bool hasWritebackToken =
4501 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4502 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00004503 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004504 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004505 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4506 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004507 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00004508 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00004509 return Error(Operands[2]->getStartLoc(),
4510 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00004511 // If we should not have writeback, there must not be a '!'. This is
4512 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004513 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00004514 return Error(Operands[3]->getStartLoc(),
4515 "writeback operator '!' not allowed when base register "
4516 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004517
4518 break;
4519 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00004520 case ARM::t2LDMIA_UPD: {
4521 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4522 return Error(Operands[4]->getStartLoc(),
4523 "writeback operator '!' not allowed when base register "
4524 "in register list");
4525 break;
4526 }
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004527 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004528 bool listContainsBase;
4529 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4530 return Error(Operands[2]->getStartLoc(),
4531 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004532 break;
4533 }
4534 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004535 bool listContainsBase;
4536 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4537 return Error(Operands[2]->getStartLoc(),
4538 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004539 break;
4540 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00004541 case ARM::tSTMIA_UPD: {
4542 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00004543 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00004544 return Error(Operands[4]->getStartLoc(),
4545 "registers must be in range r0-r7");
4546 break;
4547 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004548 }
4549
4550 return false;
4551}
4552
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004553void ARMAsmParser::
4554processInstruction(MCInst &Inst,
4555 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4556 switch (Inst.getOpcode()) {
Jim Grosbach61db5a52011-11-10 16:44:55 +00004557 // Handle the MOV complex aliases.
Jim Grosbachc14871c2011-11-10 19:18:01 +00004558 case ARM::ASRi:
4559 case ARM::LSRi:
4560 case ARM::LSLi:
4561 case ARM::RORi: {
4562 ARM_AM::ShiftOpc ShiftTy;
4563 unsigned Amt = Inst.getOperand(2).getImm();
4564 switch(Inst.getOpcode()) {
4565 default: llvm_unreachable("unexpected opcode!");
4566 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4567 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4568 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4569 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4570 }
4571 // A shift by zero is a plain MOVr, not a MOVsi.
4572 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4573 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00004574 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00004575 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00004576 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4577 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00004578 if (Opc == ARM::MOVsi)
4579 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00004580 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4581 TmpInst.addOperand(Inst.getOperand(4));
4582 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4583 Inst = TmpInst;
4584 break;
4585 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004586 case ARM::LDMIA_UPD:
4587 // If this is a load of a single register via a 'pop', then we should use
4588 // a post-indexed LDR instruction instead, per the ARM ARM.
4589 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4590 Inst.getNumOperands() == 5) {
4591 MCInst TmpInst;
4592 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4593 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4594 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4595 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4596 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4597 TmpInst.addOperand(MCOperand::CreateImm(4));
4598 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4599 TmpInst.addOperand(Inst.getOperand(3));
4600 Inst = TmpInst;
4601 }
4602 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00004603 case ARM::STMDB_UPD:
4604 // If this is a store of a single register via a 'push', then we should use
4605 // a pre-indexed STR instruction instead, per the ARM ARM.
4606 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4607 Inst.getNumOperands() == 5) {
4608 MCInst TmpInst;
4609 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4610 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4611 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4612 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4613 TmpInst.addOperand(MCOperand::CreateImm(-4));
4614 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4615 TmpInst.addOperand(Inst.getOperand(3));
4616 Inst = TmpInst;
4617 }
4618 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004619 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00004620 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4621 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4622 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4623 // to encoding T1 if <Rd> is omitted."
4624 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004625 Inst.setOpcode(ARM::tADDi3);
4626 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004627 case ARM::tSUBi8:
4628 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4629 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4630 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4631 // to encoding T1 if <Rd> is omitted."
4632 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4633 Inst.setOpcode(ARM::tSUBi3);
4634 break;
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004635 case ARM::tB:
4636 // A Thumb conditional branch outside of an IT block is a tBcc.
4637 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4638 Inst.setOpcode(ARM::tBcc);
4639 break;
4640 case ARM::t2B:
4641 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4642 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4643 Inst.setOpcode(ARM::t2Bcc);
4644 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00004645 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004646 // If the conditional is AL or we're in an IT block, we really want t2B.
4647 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbach99bc8462011-08-31 21:17:31 +00004648 Inst.setOpcode(ARM::t2B);
4649 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00004650 case ARM::tBcc:
4651 // If the conditional is AL, we really want tB.
4652 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4653 Inst.setOpcode(ARM::tB);
Jim Grosbach6ddb5682011-08-18 16:08:39 +00004654 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004655 case ARM::tLDMIA: {
4656 // If the register list contains any high registers, or if the writeback
4657 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4658 // instead if we're in Thumb2. Otherwise, this should have generated
4659 // an error in validateInstruction().
4660 unsigned Rn = Inst.getOperand(0).getReg();
4661 bool hasWritebackToken =
4662 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4663 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4664 bool listContainsBase;
4665 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4666 (!listContainsBase && !hasWritebackToken) ||
4667 (listContainsBase && hasWritebackToken)) {
4668 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4669 assert (isThumbTwo());
4670 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4671 // If we're switching to the updating version, we need to insert
4672 // the writeback tied operand.
4673 if (hasWritebackToken)
4674 Inst.insert(Inst.begin(),
4675 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4676 }
4677 break;
4678 }
Jim Grosbach099c9762011-09-16 20:50:13 +00004679 case ARM::tSTMIA_UPD: {
4680 // If the register list contains any high registers, we need to use
4681 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4682 // should have generated an error in validateInstruction().
4683 unsigned Rn = Inst.getOperand(0).getReg();
4684 bool listContainsBase;
4685 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4686 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4687 assert (isThumbTwo());
4688 Inst.setOpcode(ARM::t2STMIA_UPD);
4689 }
4690 break;
4691 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004692 case ARM::t2MOVi: {
4693 // If we can use the 16-bit encoding and the user didn't explicitly
4694 // request the 32-bit variant, transform it here.
4695 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4696 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00004697 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4698 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4699 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004700 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4701 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4702 // The operands aren't in the same order for tMOVi8...
4703 MCInst TmpInst;
4704 TmpInst.setOpcode(ARM::tMOVi8);
4705 TmpInst.addOperand(Inst.getOperand(0));
4706 TmpInst.addOperand(Inst.getOperand(4));
4707 TmpInst.addOperand(Inst.getOperand(1));
4708 TmpInst.addOperand(Inst.getOperand(2));
4709 TmpInst.addOperand(Inst.getOperand(3));
4710 Inst = TmpInst;
4711 }
4712 break;
4713 }
4714 case ARM::t2MOVr: {
4715 // If we can use the 16-bit encoding and the user didn't explicitly
4716 // request the 32-bit variant, transform it here.
4717 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4718 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4719 Inst.getOperand(2).getImm() == ARMCC::AL &&
4720 Inst.getOperand(4).getReg() == ARM::CPSR &&
4721 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4722 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4723 // The operands aren't the same for tMOV[S]r... (no cc_out)
4724 MCInst TmpInst;
4725 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4726 TmpInst.addOperand(Inst.getOperand(0));
4727 TmpInst.addOperand(Inst.getOperand(1));
4728 TmpInst.addOperand(Inst.getOperand(2));
4729 TmpInst.addOperand(Inst.getOperand(3));
4730 Inst = TmpInst;
4731 }
4732 break;
4733 }
Jim Grosbach82213192011-09-19 20:29:33 +00004734 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00004735 case ARM::t2SXTB:
4736 case ARM::t2UXTH:
4737 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00004738 // If we can use the 16-bit encoding and the user didn't explicitly
4739 // request the 32-bit variant, transform it here.
4740 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4741 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4742 Inst.getOperand(2).getImm() == 0 &&
4743 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4744 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00004745 unsigned NewOpc;
4746 switch (Inst.getOpcode()) {
4747 default: llvm_unreachable("Illegal opcode!");
4748 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4749 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4750 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4751 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4752 }
Jim Grosbach82213192011-09-19 20:29:33 +00004753 // The operands aren't the same for thumb1 (no rotate operand).
4754 MCInst TmpInst;
4755 TmpInst.setOpcode(NewOpc);
4756 TmpInst.addOperand(Inst.getOperand(0));
4757 TmpInst.addOperand(Inst.getOperand(1));
4758 TmpInst.addOperand(Inst.getOperand(3));
4759 TmpInst.addOperand(Inst.getOperand(4));
4760 Inst = TmpInst;
4761 }
4762 break;
4763 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004764 case ARM::t2IT: {
4765 // The mask bits for all but the first condition are represented as
4766 // the low bit of the condition code value implies 't'. We currently
4767 // always have 1 implies 't', so XOR toggle the bits if the low bit
4768 // of the condition code is zero. The encoding also expects the low
4769 // bit of the condition to be encoded as bit 4 of the mask operand,
4770 // so mask that in if needed
4771 MCOperand &MO = Inst.getOperand(1);
4772 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00004773 unsigned OrigMask = Mask;
4774 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004775 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004776 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4777 for (unsigned i = 3; i != TZ; --i)
4778 Mask ^= 1 << i;
4779 } else
4780 Mask |= 0x10;
4781 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00004782
4783 // Set up the IT block state according to the IT instruction we just
4784 // matched.
4785 assert(!inITBlock() && "nested IT blocks?!");
4786 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4787 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4788 ITState.CurPosition = 0;
4789 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004790 break;
4791 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004792 }
4793}
4794
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004795unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4796 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4797 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004798 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004799 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004800 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4801 assert(MCID.hasOptionalDef() &&
4802 "optionally flag setting instruction missing optional def operand");
4803 assert(MCID.NumOperands == Inst.getNumOperands() &&
4804 "operand count mismatch!");
4805 // Find the optional-def operand (cc_out).
4806 unsigned OpNo;
4807 for (OpNo = 0;
4808 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4809 ++OpNo)
4810 ;
4811 // If we're parsing Thumb1, reject it completely.
4812 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4813 return Match_MnemonicFail;
4814 // If we're parsing Thumb2, which form is legal depends on whether we're
4815 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004816 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4817 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004818 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00004819 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4820 inITBlock())
4821 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004822 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004823 // Some high-register supporting Thumb1 encodings only allow both registers
4824 // to be from r0-r7 when in Thumb2.
4825 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4826 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4827 isARMLowRegister(Inst.getOperand(2).getReg()))
4828 return Match_RequiresThumb2;
4829 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00004830 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004831 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4832 isARMLowRegister(Inst.getOperand(1).getReg()))
4833 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004834 return Match_Success;
4835}
4836
Chris Lattner9487de62010-10-28 21:28:01 +00004837bool ARMAsmParser::
4838MatchAndEmitInstruction(SMLoc IDLoc,
4839 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4840 MCStreamer &Out) {
4841 MCInst Inst;
4842 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00004843 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00004844 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00004845 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00004846 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004847 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004848 // Context sensitive operand constraints aren't handled by the matcher,
4849 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004850 if (validateInstruction(Inst, Operands)) {
4851 // Still progress the IT block, otherwise one wrong condition causes
4852 // nasty cascading errors.
4853 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004854 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004855 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004856
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004857 // Some instructions need post-processing to, for example, tweak which
4858 // encoding is selected.
4859 processInstruction(Inst, Operands);
4860
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004861 // Only move forward at the very end so that everything in validate
4862 // and process gets a consistent answer about whether we're in an IT
4863 // block.
4864 forwardITPosition();
4865
Chris Lattner9487de62010-10-28 21:28:01 +00004866 Out.EmitInstruction(Inst);
4867 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004868 case Match_MissingFeature:
4869 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4870 return true;
4871 case Match_InvalidOperand: {
4872 SMLoc ErrorLoc = IDLoc;
4873 if (ErrorInfo != ~0U) {
4874 if (ErrorInfo >= Operands.size())
4875 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00004876
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004877 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4878 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4879 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004880
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004881 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00004882 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004883 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004884 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00004885 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00004886 // The converter function will have already emited a diagnostic.
4887 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00004888 case Match_RequiresNotITBlock:
4889 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004890 case Match_RequiresITBlock:
4891 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004892 case Match_RequiresV6:
4893 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4894 case Match_RequiresThumb2:
4895 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004896 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004897
Eric Christopher91d7b902010-10-29 09:26:59 +00004898 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004899 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00004900}
4901
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004902/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00004903bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4904 StringRef IDVal = DirectiveID.getIdentifier();
4905 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004906 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004907 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004908 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004909 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004910 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004911 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004912 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004913 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004914 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00004915 return true;
4916}
4917
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004918/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00004919/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004920bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00004921 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4922 for (;;) {
4923 const MCExpr *Value;
4924 if (getParser().ParseExpression(Value))
4925 return true;
4926
Chris Lattnerc35681b2010-01-19 19:46:13 +00004927 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00004928
4929 if (getLexer().is(AsmToken::EndOfStatement))
4930 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00004931
Kevin Enderbyccab3172009-09-15 00:27:25 +00004932 // FIXME: Improve diagnostic.
4933 if (getLexer().isNot(AsmToken::Comma))
4934 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004935 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004936 }
4937 }
4938
Sean Callanana83fd7d2010-01-19 20:27:46 +00004939 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004940 return false;
4941}
4942
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004943/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00004944/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004945bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00004946 if (getLexer().isNot(AsmToken::EndOfStatement))
4947 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004948 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004949
4950 // TODO: set thumb mode
4951 // TODO: tell the MC streamer the mode
4952 // getParser().getStreamer().Emit???();
4953 return false;
4954}
4955
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004956/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00004957/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004958bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004959 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4960 bool isMachO = MAI.hasSubsectionsViaSymbols();
4961 StringRef Name;
4962
4963 // Darwin asm has function name after .thumb_func direction
4964 // ELF doesn't
4965 if (isMachO) {
4966 const AsmToken &Tok = Parser.getTok();
4967 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4968 return Error(L, "unexpected token in .thumb_func directive");
4969 Name = Tok.getString();
4970 Parser.Lex(); // Consume the identifier token.
4971 }
4972
Kevin Enderby146dcf22009-10-15 20:48:48 +00004973 if (getLexer().isNot(AsmToken::EndOfStatement))
4974 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004975 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004976
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004977 // FIXME: assuming function name will be the line following .thumb_func
4978 if (!isMachO) {
4979 Name = Parser.getTok().getString();
4980 }
4981
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00004982 // Mark symbol as a thumb symbol.
4983 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4984 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004985 return false;
4986}
4987
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004988/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00004989/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004990bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004991 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004992 if (Tok.isNot(AsmToken::Identifier))
4993 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00004994 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00004995 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00004996 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004997 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00004998 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00004999 else
5000 return Error(L, "unrecognized syntax mode in .syntax directive");
5001
5002 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00005003 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005004 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005005
5006 // TODO tell the MC streamer the mode
5007 // getParser().getStreamer().Emit???();
5008 return false;
5009}
5010
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005011/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00005012/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005013bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00005014 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005015 if (Tok.isNot(AsmToken::Integer))
5016 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00005017 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00005018 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00005019 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00005020 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00005021 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005022 else
5023 return Error(L, "invalid operand to .code directive");
5024
5025 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00005026 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005027 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005028
Evan Cheng284b4672011-07-08 22:36:29 +00005029 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00005030 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00005031 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00005032 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00005033 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00005034 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00005035 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00005036 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00005037 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00005038
Kevin Enderby146dcf22009-10-15 20:48:48 +00005039 return false;
5040}
5041
Sean Callanan643a5572010-04-07 20:29:34 +00005042extern "C" void LLVMInitializeARMAsmLexer();
5043
Kevin Enderby8be42bd2009-10-30 22:55:57 +00005044/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00005045extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00005046 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5047 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00005048 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005049}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00005050
Chris Lattner3e4582a2010-09-06 19:11:01 +00005051#define GET_REGISTER_MATCHER
5052#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00005053#include "ARMGenAsmMatcher.inc"