blob: 1d6a05cff956fd8f9eb614b9f430997ee2771b6f [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"
Owen Andersona098d152011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar188b47b2010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000036
Kevin Enderbyccab3172009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +000039namespace {
Bill Wendlingee7f1f92010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach624bcc72010-10-29 14:46:02 +000042
Evan Cheng11424442011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbached16ec42011-08-29 22:24:09 +000047 struct {
48 ARMCC::CondCodes Cond; // Condition for IT block.
49 unsigned Mask:4; // Condition mask for instructions.
50 // Starting at first 1 (from lsb).
51 // '1' condition as indicated in IT.
52 // '0' inverse of condition (else).
53 // Count of instructions in IT block is
54 // 4 - trailingzeroes(mask)
55
56 bool FirstCond; // Explicit flag for when we're parsing the
57 // First instruction in the IT block. It's
58 // implied in the mask, so needs special
59 // handling.
60
61 unsigned CurPosition; // Current position in parsing of IT
62 // block. In range [0,3]. Initialized
63 // according to count of instructions in block.
64 // ~0U if no active IT block.
65 } ITState;
66 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000067 void forwardITPosition() {
68 if (!inITBlock()) return;
69 // Move to the next instruction in the IT block, if there is one. If not,
70 // mark the block as done.
71 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
72 if (++ITState.CurPosition == 5 - TZ)
73 ITState.CurPosition = ~0U; // Done with the IT block after this.
74 }
Jim Grosbached16ec42011-08-29 22:24:09 +000075
76
Kevin Enderbyccab3172009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000078 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
79
80 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000092 bool parseDirectiveWord(unsigned Size, SMLoc L);
93 bool parseDirectiveThumb(SMLoc L);
94 bool parseDirectiveThumbFunc(SMLoc L);
95 bool parseDirectiveCode(SMLoc L);
96 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +000097
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000103
Evan Cheng4d1ca962011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000107 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000110 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloy21efa7d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng284b4672011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000123 }
James Molloy21efa7d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000127
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000130
Chris Lattner3e4582a2010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000133
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000141 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000143 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000147 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
148 StringRef Op, int Low, int High);
149 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
150 return parsePKHImm(O, "lsl", 0, 31);
151 }
152 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
153 return parsePKHImm(O, "asr", 1, 32);
154 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000155 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000156 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000157 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000158 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000159 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000160 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000161 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000162
163 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000164 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
165 const SmallVectorImpl<MCParsedAsmOperand*> &);
166 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000168 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000170 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000172 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000174 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000176 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000178 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000180 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000182 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
184 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000190 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000192 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000194 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000196 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000198
199 bool validateInstruction(MCInst &Inst,
200 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000201 void processInstruction(MCInst &Inst,
202 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000203 bool shouldOmitCCOutOperand(StringRef Mnemonic,
204 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000205
Kevin Enderbyccab3172009-09-15 00:27:25 +0000206public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000207 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000208 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000209 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000210 Match_RequiresV6,
211 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000212 };
213
Evan Cheng91111d22011-07-09 05:47:46 +0000214 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000215 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000216 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000217
Evan Cheng4d1ca962011-07-08 01:53:10 +0000218 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000219 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000220
221 // Not in an ITBlock to start with.
222 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000223 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000224
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000225 // Implementation of the MCTargetAsmParser interface:
226 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
227 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000228 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000229 bool ParseDirective(AsmToken DirectiveID);
230
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000231 unsigned checkTargetMatchPredicate(MCInst &Inst);
232
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000233 bool MatchAndEmitInstruction(SMLoc IDLoc,
234 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
235 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000236};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000237} // end anonymous namespace
238
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000239namespace {
240
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000241/// ARMOperand - Instances of this class represent a parsed ARM machine
242/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000243class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000244 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000245 k_CondCode,
246 k_CCOut,
247 k_ITCondMask,
248 k_CoprocNum,
249 k_CoprocReg,
250 k_Immediate,
251 k_FPImmediate,
252 k_MemBarrierOpt,
253 k_Memory,
254 k_PostIndexRegister,
255 k_MSRMask,
256 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000257 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000258 k_Register,
259 k_RegisterList,
260 k_DPRRegisterList,
261 k_SPRRegisterList,
262 k_ShiftedRegister,
263 k_ShiftedImmediate,
264 k_ShifterImmediate,
265 k_RotateImmediate,
266 k_BitfieldDescriptor,
267 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000268 } Kind;
269
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000270 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000271 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000272
273 union {
274 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000275 ARMCC::CondCodes Val;
276 } CC;
277
278 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000279 unsigned Val;
280 } Cop;
281
282 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000283 unsigned Mask:4;
284 } ITMask;
285
286 struct {
287 ARM_MB::MemBOpt Val;
288 } MBOpt;
289
290 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000291 ARM_PROC::IFlags Val;
292 } IFlags;
293
294 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000295 unsigned Val;
296 } MMask;
297
298 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000299 const char *Data;
300 unsigned Length;
301 } Tok;
302
303 struct {
304 unsigned RegNum;
305 } Reg;
306
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000307 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000308 unsigned Val;
309 } VectorIndex;
310
311 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000312 const MCExpr *Val;
313 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000314
Jim Grosbache7fbce72011-10-03 23:38:36 +0000315 struct {
316 unsigned Val; // encoded 8-bit representation
317 } FPImm;
318
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000319 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000320 struct {
321 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000322 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
323 // was specified.
324 const MCConstantExpr *OffsetImm; // Offset immediate value
325 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
326 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach3d0b3a32011-08-05 22:03:36 +0000327 unsigned ShiftImm; // shift for OffsetReg.
Jim Grosbachd3595712011-08-03 23:50:40 +0000328 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000329 } Mem;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000330
331 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000332 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000333 bool isAdd;
334 ARM_AM::ShiftOpc ShiftTy;
335 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000336 } PostIdxReg;
337
338 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000339 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000340 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000341 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000342 struct {
343 ARM_AM::ShiftOpc ShiftTy;
344 unsigned SrcReg;
345 unsigned ShiftReg;
346 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000347 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000348 struct {
349 ARM_AM::ShiftOpc ShiftTy;
350 unsigned SrcReg;
351 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000352 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000353 struct {
354 unsigned Imm;
355 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000356 struct {
357 unsigned LSB;
358 unsigned Width;
359 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000360 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000361
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000362 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
363public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000364 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
365 Kind = o.Kind;
366 StartLoc = o.StartLoc;
367 EndLoc = o.EndLoc;
368 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000369 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000370 CC = o.CC;
371 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000372 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000373 ITMask = o.ITMask;
374 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000375 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000376 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000377 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000378 case k_CCOut:
379 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000380 Reg = o.Reg;
381 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000382 case k_RegisterList:
383 case k_DPRRegisterList:
384 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000385 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000386 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000387 case k_CoprocNum:
388 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000389 Cop = o.Cop;
390 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000391 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000392 Imm = o.Imm;
393 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000394 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000395 FPImm = o.FPImm;
396 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000397 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000398 MBOpt = o.MBOpt;
399 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000400 case k_Memory:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000401 Mem = o.Mem;
402 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000403 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000404 PostIdxReg = o.PostIdxReg;
405 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000406 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000407 MMask = o.MMask;
408 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000409 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000410 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000411 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000412 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000413 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000414 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000415 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000416 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000417 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000418 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000419 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000420 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000421 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000422 RotImm = o.RotImm;
423 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000424 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000425 Bitfield = o.Bitfield;
426 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000427 case k_VectorIndex:
428 VectorIndex = o.VectorIndex;
429 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000430 }
431 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000432
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000433 /// getStartLoc - Get the location of the first token of this operand.
434 SMLoc getStartLoc() const { return StartLoc; }
435 /// getEndLoc - Get the location of the last token of this operand.
436 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000437
Daniel Dunbard8042b72010-08-11 06:36:53 +0000438 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000439 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000440 return CC.Val;
441 }
442
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000443 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000444 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000445 return Cop.Val;
446 }
447
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000448 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000449 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000450 return StringRef(Tok.Data, Tok.Length);
451 }
452
453 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000454 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000455 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000456 }
457
Bill Wendlingbed94652010-11-09 23:28:44 +0000458 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000459 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
460 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000461 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000462 }
463
Kevin Enderbyf5079942009-10-13 22:19:02 +0000464 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000465 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000466 return Imm.Val;
467 }
468
Jim Grosbache7fbce72011-10-03 23:38:36 +0000469 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000470 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000471 return FPImm.Val;
472 }
473
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000474 unsigned getVectorIndex() const {
475 assert(Kind == k_VectorIndex && "Invalid access!");
476 return VectorIndex.Val;
477 }
478
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000479 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000480 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000481 return MBOpt.Val;
482 }
483
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000484 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000485 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000486 return IFlags.Val;
487 }
488
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000489 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000490 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000491 return MMask.Val;
492 }
493
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000494 bool isCoprocNum() const { return Kind == k_CoprocNum; }
495 bool isCoprocReg() const { return Kind == k_CoprocReg; }
496 bool isCondCode() const { return Kind == k_CondCode; }
497 bool isCCOut() const { return Kind == k_CCOut; }
498 bool isITMask() const { return Kind == k_ITCondMask; }
499 bool isITCondCode() const { return Kind == k_CondCode; }
500 bool isImm() const { return Kind == k_Immediate; }
501 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000502 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000503 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000504 return false;
505 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
506 if (!CE) return false;
507 int64_t Value = CE->getValue();
508 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
509 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000510 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000511 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000512 return false;
513 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
514 if (!CE) return false;
515 int64_t Value = CE->getValue();
516 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
517 }
518 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000519 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000520 return false;
521 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
522 if (!CE) return false;
523 int64_t Value = CE->getValue();
524 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
525 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000526 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000527 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000528 return false;
529 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
530 if (!CE) return false;
531 int64_t Value = CE->getValue();
532 return Value >= 0 && Value < 256;
533 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000534 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000535 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000536 return false;
537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
538 if (!CE) return false;
539 int64_t Value = CE->getValue();
540 return Value >= 0 && Value < 8;
541 }
542 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000543 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000544 return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return Value >= 0 && Value < 16;
549 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000550 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return Value >= 0 && Value < 32;
557 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000558 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return Value > 0 && Value < 17;
565 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000566 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return Value > 0 && Value < 33;
573 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000574 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000575 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 65536;
581 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000582 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000583 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 // If it's not a constant expression, it'll generate a fixup and be
587 // handled later.
588 if (!CE) return true;
589 int64_t Value = CE->getValue();
590 return Value >= 0 && Value < 65536;
591 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000592 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000593 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000594 return false;
595 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
596 if (!CE) return false;
597 int64_t Value = CE->getValue();
598 return Value >= 0 && Value <= 0xffffff;
599 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000600 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000601 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000602 return false;
603 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
604 if (!CE) return false;
605 int64_t Value = CE->getValue();
606 return Value > 0 && Value < 33;
607 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000608 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000609 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000610 return false;
611 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
612 if (!CE) return false;
613 int64_t Value = CE->getValue();
614 return Value >= 0 && Value < 32;
615 }
616 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000617 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000618 return false;
619 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
620 if (!CE) return false;
621 int64_t Value = CE->getValue();
622 return Value > 0 && Value <= 32;
623 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000624 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000625 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000626 return false;
627 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
628 if (!CE) return false;
629 int64_t Value = CE->getValue();
630 return ARM_AM::getSOImmVal(Value) != -1;
631 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000632 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000633 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000634 return false;
635 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
636 if (!CE) return false;
637 int64_t Value = CE->getValue();
638 return ARM_AM::getT2SOImmVal(Value) != -1;
639 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000640 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000641 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000642 return false;
643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value == 1 || Value == 0;
647 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000648 bool isReg() const { return Kind == k_Register; }
649 bool isRegList() const { return Kind == k_RegisterList; }
650 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
651 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
652 bool isToken() const { return Kind == k_Token; }
653 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
654 bool isMemory() const { return Kind == k_Memory; }
655 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
656 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
657 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
658 bool isRotImm() const { return Kind == k_RotateImmediate; }
659 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
660 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000661 bool isPostIdxReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000662 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000663 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000664 bool isMemNoOffset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000665 if (Kind != k_Memory)
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000666 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000667 // No offset of any kind.
668 return Mem.OffsetRegNum == 0 && Mem.OffsetImm == 0;
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000669 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000670 bool isAddrMode2() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000671 if (Kind != k_Memory)
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000672 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000673 // Check for register offset.
674 if (Mem.OffsetRegNum) return true;
675 // Immediate offset in range [-4095, 4095].
676 if (!Mem.OffsetImm) return true;
677 int64_t Val = Mem.OffsetImm->getValue();
678 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000679 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000680 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000681 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000682 return false;
683 // Immediate offset in range [-4095, 4095].
684 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
685 if (!CE) return false;
686 int64_t Val = CE->getValue();
687 return Val > -4096 && Val < 4096;
688 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000689 bool isAddrMode3() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000690 if (Kind != k_Memory)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000691 return false;
692 // No shifts are legal for AM3.
693 if (Mem.ShiftType != ARM_AM::no_shift) return false;
694 // Check for register offset.
695 if (Mem.OffsetRegNum) return true;
696 // Immediate offset in range [-255, 255].
697 if (!Mem.OffsetImm) return true;
698 int64_t Val = Mem.OffsetImm->getValue();
699 return Val > -256 && Val < 256;
700 }
701 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000702 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000703 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000704 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000705 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
706 // Immediate offset in range [-255, 255].
707 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
708 if (!CE) return false;
709 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000710 // Special case, #-0 is INT32_MIN.
711 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000712 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000713 bool isAddrMode5() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000714 if (Kind != k_Memory)
Bill Wendling8d2aa032010-11-08 23:49:57 +0000715 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000716 // Check for register offset.
717 if (Mem.OffsetRegNum) return false;
718 // Immediate offset in range [-1020, 1020] and a multiple of 4.
719 if (!Mem.OffsetImm) return true;
720 int64_t Val = Mem.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000721 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
722 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000723 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000724 bool isMemTBB() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000725 if (Kind != k_Memory || !Mem.OffsetRegNum || Mem.isNegative ||
Jim Grosbach05541f42011-09-19 22:21:13 +0000726 Mem.ShiftType != ARM_AM::no_shift)
727 return false;
728 return true;
729 }
730 bool isMemTBH() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000731 if (Kind != k_Memory || !Mem.OffsetRegNum || Mem.isNegative ||
Jim Grosbach05541f42011-09-19 22:21:13 +0000732 Mem.ShiftType != ARM_AM::lsl || Mem.ShiftImm != 1)
733 return false;
734 return true;
735 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000736 bool isMemRegOffset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000737 if (Kind != k_Memory || !Mem.OffsetRegNum)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000738 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000739 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000740 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000741 bool isT2MemRegOffset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000742 if (Kind != k_Memory || !Mem.OffsetRegNum || Mem.isNegative)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000743 return false;
744 // Only lsl #{0, 1, 2, 3} allowed.
745 if (Mem.ShiftType == ARM_AM::no_shift)
746 return true;
747 if (Mem.ShiftType != ARM_AM::lsl || Mem.ShiftImm > 3)
748 return false;
749 return true;
750 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000751 bool isMemThumbRR() const {
752 // Thumb reg+reg addressing is simple. Just two registers, a base and
753 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000754 if (Kind != k_Memory || !Mem.OffsetRegNum || Mem.isNegative ||
Jim Grosbachd3595712011-08-03 23:50:40 +0000755 Mem.ShiftType != ARM_AM::no_shift)
Bill Wendling811c9362010-11-30 07:44:32 +0000756 return false;
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000757 return isARMLowRegister(Mem.BaseRegNum) &&
758 (!Mem.OffsetRegNum || isARMLowRegister(Mem.OffsetRegNum));
759 }
760 bool isMemThumbRIs4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000761 if (Kind != k_Memory || Mem.OffsetRegNum != 0 ||
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000762 !isARMLowRegister(Mem.BaseRegNum))
763 return false;
764 // Immediate offset, multiple of 4 in range [0, 124].
765 if (!Mem.OffsetImm) return true;
766 int64_t Val = Mem.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000767 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
768 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000769 bool isMemThumbRIs2() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000770 if (Kind != k_Memory || Mem.OffsetRegNum != 0 ||
Jim Grosbach26d35872011-08-19 18:55:51 +0000771 !isARMLowRegister(Mem.BaseRegNum))
772 return false;
773 // Immediate offset, multiple of 4 in range [0, 62].
774 if (!Mem.OffsetImm) return true;
775 int64_t Val = Mem.OffsetImm->getValue();
776 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
777 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000778 bool isMemThumbRIs1() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000779 if (Kind != k_Memory || Mem.OffsetRegNum != 0 ||
Jim Grosbacha32c7532011-08-19 18:49:59 +0000780 !isARMLowRegister(Mem.BaseRegNum))
781 return false;
782 // Immediate offset in range [0, 31].
783 if (!Mem.OffsetImm) return true;
784 int64_t Val = Mem.OffsetImm->getValue();
785 return Val >= 0 && Val <= 31;
786 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000787 bool isMemThumbSPI() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000788 if (Kind != k_Memory || Mem.OffsetRegNum != 0 || Mem.BaseRegNum != ARM::SP)
Jim Grosbach23983d62011-08-19 18:13:48 +0000789 return false;
790 // Immediate offset, multiple of 4 in range [0, 1020].
791 if (!Mem.OffsetImm) return true;
792 int64_t Val = Mem.OffsetImm->getValue();
793 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000794 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000795 bool isMemImm8s4Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000796 if (Kind != k_Memory || Mem.OffsetRegNum != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000797 return false;
798 // Immediate offset a multiple of 4 in range [-1020, 1020].
799 if (!Mem.OffsetImm) return true;
800 int64_t Val = Mem.OffsetImm->getValue();
801 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
802 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000803 bool isMemImm0_1020s4Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000804 if (Kind != k_Memory || Mem.OffsetRegNum != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +0000805 return false;
806 // Immediate offset a multiple of 4 in range [0, 1020].
807 if (!Mem.OffsetImm) return true;
808 int64_t Val = Mem.OffsetImm->getValue();
809 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
810 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000811 bool isMemImm8Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000812 if (Kind != k_Memory || Mem.OffsetRegNum != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000813 return false;
814 // Immediate offset in range [-255, 255].
815 if (!Mem.OffsetImm) return true;
816 int64_t Val = Mem.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +0000817 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +0000818 }
Jim Grosbach2392c532011-09-07 23:39:14 +0000819 bool isMemPosImm8Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000820 if (Kind != k_Memory || Mem.OffsetRegNum != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +0000821 return false;
822 // Immediate offset in range [0, 255].
823 if (!Mem.OffsetImm) return true;
824 int64_t Val = Mem.OffsetImm->getValue();
825 return Val >= 0 && Val < 256;
826 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000827 bool isMemNegImm8Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000828 if (Kind != k_Memory || Mem.OffsetRegNum != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000829 return false;
830 // Immediate offset in range [-255, -1].
831 if (!Mem.OffsetImm) return true;
832 int64_t Val = Mem.OffsetImm->getValue();
833 return Val > -256 && Val < 0;
834 }
835 bool isMemUImm12Offset() const {
836 // If we have an immediate that's not a constant, treat it as a label
837 // reference needing a fixup. If it is a constant, it's something else
838 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000839 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000840 return true;
841
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000842 if (Kind != k_Memory || Mem.OffsetRegNum != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000843 return false;
844 // Immediate offset in range [0, 4095].
845 if (!Mem.OffsetImm) return true;
846 int64_t Val = Mem.OffsetImm->getValue();
847 return (Val >= 0 && Val < 4096);
848 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000849 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +0000850 // If we have an immediate that's not a constant, treat it as a label
851 // reference needing a fixup. If it is a constant, it's something else
852 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000853 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +0000854 return true;
855
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000856 if (Kind != k_Memory || Mem.OffsetRegNum != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000857 return false;
858 // Immediate offset in range [-4095, 4095].
859 if (!Mem.OffsetImm) return true;
860 int64_t Val = Mem.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000861 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000862 }
863 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000864 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +0000865 return false;
866 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
867 if (!CE) return false;
868 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +0000869 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000870 }
871
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000872 bool isMSRMask() const { return Kind == k_MSRMask; }
873 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000874
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000875 bool isVectorIndex8() const {
876 if (Kind != k_VectorIndex) return false;
877 return VectorIndex.Val < 8;
878 }
879 bool isVectorIndex16() const {
880 if (Kind != k_VectorIndex) return false;
881 return VectorIndex.Val < 4;
882 }
883 bool isVectorIndex32() const {
884 if (Kind != k_VectorIndex) return false;
885 return VectorIndex.Val < 2;
886 }
887
888
889
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000890 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +0000891 // Add as immediates when possible. Null MCExpr = 0.
892 if (Expr == 0)
893 Inst.addOperand(MCOperand::CreateImm(0));
894 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000895 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
896 else
897 Inst.addOperand(MCOperand::CreateExpr(Expr));
898 }
899
Daniel Dunbard8042b72010-08-11 06:36:53 +0000900 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +0000901 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000902 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +0000903 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
904 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +0000905 }
906
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000907 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
908 assert(N == 1 && "Invalid number of operands!");
909 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
910 }
911
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000912 void addITMaskOperands(MCInst &Inst, unsigned N) const {
913 assert(N == 1 && "Invalid number of operands!");
914 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
915 }
916
917 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
918 assert(N == 1 && "Invalid number of operands!");
919 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
920 }
921
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000922 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
923 assert(N == 1 && "Invalid number of operands!");
924 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
925 }
926
Jim Grosbach0bfb4d52010-12-06 18:21:12 +0000927 void addCCOutOperands(MCInst &Inst, unsigned N) const {
928 assert(N == 1 && "Invalid number of operands!");
929 Inst.addOperand(MCOperand::CreateReg(getReg()));
930 }
931
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000932 void addRegOperands(MCInst &Inst, unsigned N) const {
933 assert(N == 1 && "Invalid number of operands!");
934 Inst.addOperand(MCOperand::CreateReg(getReg()));
935 }
936
Jim Grosbachac798e12011-07-25 20:49:51 +0000937 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000938 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +0000939 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
940 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
941 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000942 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +0000943 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000944 }
945
Jim Grosbachac798e12011-07-25 20:49:51 +0000946 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +0000947 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +0000948 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
949 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +0000950 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +0000951 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +0000952 }
953
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000954 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000955 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000956 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
957 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000958 }
959
Bill Wendling8d2aa032010-11-08 23:49:57 +0000960 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +0000961 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +0000962 const SmallVectorImpl<unsigned> &RegList = getRegList();
963 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +0000964 I = RegList.begin(), E = RegList.end(); I != E; ++I)
965 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +0000966 }
967
Bill Wendling9898ac92010-11-17 04:32:08 +0000968 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
969 addRegListOperands(Inst, N);
970 }
971
972 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
973 addRegListOperands(Inst, N);
974 }
975
Jim Grosbach833b9d32011-07-27 20:15:40 +0000976 void addRotImmOperands(MCInst &Inst, unsigned N) const {
977 assert(N == 1 && "Invalid number of operands!");
978 // Encoded as val>>3. The printer handles display as 8, 16, 24.
979 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
980 }
981
Jim Grosbach864b6092011-07-28 21:34:26 +0000982 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
983 assert(N == 1 && "Invalid number of operands!");
984 // Munge the lsb/width into a bitfield mask.
985 unsigned lsb = Bitfield.LSB;
986 unsigned width = Bitfield.Width;
987 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
988 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
989 (32 - (lsb + width)));
990 Inst.addOperand(MCOperand::CreateImm(Mask));
991 }
992
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000993 void addImmOperands(MCInst &Inst, unsigned N) const {
994 assert(N == 1 && "Invalid number of operands!");
995 addExpr(Inst, getImm());
996 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000997
Jim Grosbache7fbce72011-10-03 23:38:36 +0000998 void addFPImmOperands(MCInst &Inst, unsigned N) const {
999 assert(N == 1 && "Invalid number of operands!");
1000 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1001 }
1002
Jim Grosbach7db8d692011-09-08 22:07:06 +00001003 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1004 assert(N == 1 && "Invalid number of operands!");
1005 // FIXME: We really want to scale the value here, but the LDRD/STRD
1006 // instruction don't encode operands that way yet.
1007 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1008 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1009 }
1010
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001011 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1012 assert(N == 1 && "Invalid number of operands!");
1013 // The immediate is scaled by four in the encoding and is stored
1014 // in the MCInst as such. Lop off the low two bits here.
1015 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1016 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1017 }
1018
1019 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
1021 // The immediate is scaled by four in the encoding and is stored
1022 // in the MCInst as such. Lop off the low two bits here.
1023 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1024 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1025 }
1026
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001027 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1028 assert(N == 1 && "Invalid number of operands!");
1029 addExpr(Inst, getImm());
1030 }
1031
Jim Grosbach31756c22011-07-13 22:01:08 +00001032 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1033 assert(N == 1 && "Invalid number of operands!");
1034 addExpr(Inst, getImm());
1035 }
1036
1037 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1038 assert(N == 1 && "Invalid number of operands!");
1039 addExpr(Inst, getImm());
1040 }
1041
Jim Grosbach72e7c4f2011-07-21 23:26:25 +00001042 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1043 assert(N == 1 && "Invalid number of operands!");
1044 addExpr(Inst, getImm());
1045 }
1046
Jim Grosbach475c6db2011-07-25 23:09:14 +00001047 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1048 assert(N == 1 && "Invalid number of operands!");
1049 // The constant encodes as the immediate-1, and we store in the instruction
1050 // the bits as encoded, so subtract off one here.
1051 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1052 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1053 }
1054
Jim Grosbach801e0a32011-07-22 23:16:18 +00001055 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1056 assert(N == 1 && "Invalid number of operands!");
1057 // The constant encodes as the immediate-1, and we store in the instruction
1058 // the bits as encoded, so subtract off one here.
1059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1060 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1061 }
1062
Jim Grosbach975b6412011-07-13 20:10:10 +00001063 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1064 assert(N == 1 && "Invalid number of operands!");
1065 addExpr(Inst, getImm());
1066 }
1067
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00001068 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1069 assert(N == 1 && "Invalid number of operands!");
1070 addExpr(Inst, getImm());
1071 }
1072
Jim Grosbachf1637842011-07-26 16:24:27 +00001073 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1074 assert(N == 1 && "Invalid number of operands!");
1075 addExpr(Inst, getImm());
1076 }
1077
Jim Grosbach46dd4132011-08-17 21:51:27 +00001078 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1079 assert(N == 1 && "Invalid number of operands!");
1080 // The constant encodes as the immediate, except for 32, which encodes as
1081 // zero.
1082 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1083 unsigned Imm = CE->getValue();
1084 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1085 }
1086
Jim Grosbach27c1e252011-07-21 17:23:04 +00001087 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 addExpr(Inst, getImm());
1090 }
1091
1092 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
1094 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1095 // the instruction as well.
1096 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1097 int Val = CE->getValue();
1098 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1099 }
1100
Jim Grosbach9720dcf2011-07-19 16:50:30 +00001101 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1102 assert(N == 1 && "Invalid number of operands!");
1103 addExpr(Inst, getImm());
1104 }
1105
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001106 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1107 assert(N == 1 && "Invalid number of operands!");
1108 addExpr(Inst, getImm());
1109 }
1110
Jim Grosbach0a547702011-07-22 17:44:50 +00001111 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
1113 addExpr(Inst, getImm());
1114 }
1115
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001116 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!");
1118 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1119 }
1120
Jim Grosbachd3595712011-08-03 23:50:40 +00001121 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
1123 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001124 }
1125
Jim Grosbachd3595712011-08-03 23:50:40 +00001126 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1127 assert(N == 3 && "Invalid number of operands!");
1128 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1129 if (!Mem.OffsetRegNum) {
1130 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1131 // Special case for #-0
1132 if (Val == INT32_MIN) Val = 0;
1133 if (Val < 0) Val = -Val;
1134 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1135 } else {
1136 // For register offset, we encode the shift type and negation flag
1137 // here.
1138 Val = ARM_AM::getAM2Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add,
Jim Grosbacha2b8b602011-08-11 22:05:09 +00001139 Mem.ShiftImm, Mem.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001140 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001141 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1142 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1143 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001144 }
1145
Jim Grosbachcd17c122011-08-04 23:01:30 +00001146 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1147 assert(N == 2 && "Invalid number of operands!");
1148 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1149 assert(CE && "non-constant AM2OffsetImm operand!");
1150 int32_t Val = CE->getValue();
1151 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1152 // Special case for #-0
1153 if (Val == INT32_MIN) Val = 0;
1154 if (Val < 0) Val = -Val;
1155 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1156 Inst.addOperand(MCOperand::CreateReg(0));
1157 Inst.addOperand(MCOperand::CreateImm(Val));
1158 }
1159
Jim Grosbach5b96b802011-08-10 20:29:19 +00001160 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1161 assert(N == 3 && "Invalid number of operands!");
1162 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1163 if (!Mem.OffsetRegNum) {
1164 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1165 // Special case for #-0
1166 if (Val == INT32_MIN) Val = 0;
1167 if (Val < 0) Val = -Val;
1168 Val = ARM_AM::getAM3Opc(AddSub, Val);
1169 } else {
1170 // For register offset, we encode the shift type and negation flag
1171 // here.
1172 Val = ARM_AM::getAM3Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
1173 }
1174 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1175 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1176 Inst.addOperand(MCOperand::CreateImm(Val));
1177 }
1178
1179 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001181 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001182 int32_t Val =
1183 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1184 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1185 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001186 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001187 }
1188
1189 // Constant offset.
1190 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1191 int32_t Val = CE->getValue();
1192 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1193 // Special case for #-0
1194 if (Val == INT32_MIN) Val = 0;
1195 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001196 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001197 Inst.addOperand(MCOperand::CreateReg(0));
1198 Inst.addOperand(MCOperand::CreateImm(Val));
1199 }
1200
Jim Grosbachd3595712011-08-03 23:50:40 +00001201 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1202 assert(N == 2 && "Invalid number of operands!");
1203 // The lower two bits are always zero and as such are not encoded.
1204 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() / 4 : 0;
1205 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1206 // Special case for #-0
1207 if (Val == INT32_MIN) Val = 0;
1208 if (Val < 0) Val = -Val;
1209 Val = ARM_AM::getAM5Opc(AddSub, Val);
1210 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1211 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001212 }
1213
Jim Grosbach7db8d692011-09-08 22:07:06 +00001214 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1215 assert(N == 2 && "Invalid number of operands!");
1216 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1217 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1218 Inst.addOperand(MCOperand::CreateImm(Val));
1219 }
1220
Jim Grosbacha05627e2011-09-09 18:37:27 +00001221 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1222 assert(N == 2 && "Invalid number of operands!");
1223 // The lower two bits are always zero and as such are not encoded.
1224 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() / 4 : 0;
1225 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1226 Inst.addOperand(MCOperand::CreateImm(Val));
1227 }
1228
Jim Grosbachd3595712011-08-03 23:50:40 +00001229 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1230 assert(N == 2 && "Invalid number of operands!");
1231 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1232 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1233 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001234 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001235
Jim Grosbach2392c532011-09-07 23:39:14 +00001236 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1237 addMemImm8OffsetOperands(Inst, N);
1238 }
1239
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001240 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001241 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001242 }
1243
1244 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 2 && "Invalid number of operands!");
1246 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001247 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001248 addExpr(Inst, getImm());
1249 Inst.addOperand(MCOperand::CreateImm(0));
1250 return;
1251 }
1252
1253 // Otherwise, it's a normal memory reg+offset.
1254 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1255 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1256 Inst.addOperand(MCOperand::CreateImm(Val));
1257 }
1258
Jim Grosbachd3595712011-08-03 23:50:40 +00001259 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1260 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001261 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001262 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001263 addExpr(Inst, getImm());
1264 Inst.addOperand(MCOperand::CreateImm(0));
1265 return;
1266 }
1267
1268 // Otherwise, it's a normal memory reg+offset.
Jim Grosbachd3595712011-08-03 23:50:40 +00001269 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1270 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1271 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001272 }
Bill Wendling811c9362010-11-30 07:44:32 +00001273
Jim Grosbach05541f42011-09-19 22:21:13 +00001274 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1275 assert(N == 2 && "Invalid number of operands!");
1276 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1277 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1278 }
1279
1280 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 2 && "Invalid number of operands!");
1282 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1283 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1284 }
1285
Jim Grosbachd3595712011-08-03 23:50:40 +00001286 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1287 assert(N == 3 && "Invalid number of operands!");
1288 unsigned Val = ARM_AM::getAM2Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001289 Mem.ShiftImm, Mem.ShiftType);
Jim Grosbachd3595712011-08-03 23:50:40 +00001290 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1291 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1292 Inst.addOperand(MCOperand::CreateImm(Val));
1293 }
1294
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001295 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 3 && "Invalid number of operands!");
1297 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1298 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1299 Inst.addOperand(MCOperand::CreateImm(Mem.ShiftImm));
1300 }
1301
Jim Grosbachd3595712011-08-03 23:50:40 +00001302 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1303 assert(N == 2 && "Invalid number of operands!");
1304 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1305 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1306 }
1307
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001308 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1309 assert(N == 2 && "Invalid number of operands!");
1310 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 4) : 0;
1311 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1312 Inst.addOperand(MCOperand::CreateImm(Val));
1313 }
1314
Jim Grosbach26d35872011-08-19 18:55:51 +00001315 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1316 assert(N == 2 && "Invalid number of operands!");
1317 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 2) : 0;
1318 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1319 Inst.addOperand(MCOperand::CreateImm(Val));
1320 }
1321
Jim Grosbacha32c7532011-08-19 18:49:59 +00001322 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1323 assert(N == 2 && "Invalid number of operands!");
1324 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue()) : 0;
1325 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1326 Inst.addOperand(MCOperand::CreateImm(Val));
1327 }
1328
Jim Grosbach23983d62011-08-19 18:13:48 +00001329 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1330 assert(N == 2 && "Invalid number of operands!");
1331 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 4) : 0;
1332 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1333 Inst.addOperand(MCOperand::CreateImm(Val));
1334 }
1335
Jim Grosbachd3595712011-08-03 23:50:40 +00001336 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1337 assert(N == 1 && "Invalid number of operands!");
1338 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1339 assert(CE && "non-constant post-idx-imm8 operand!");
1340 int Imm = CE->getValue();
1341 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001342 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001343 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1344 Inst.addOperand(MCOperand::CreateImm(Imm));
1345 }
1346
1347 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1348 assert(N == 2 && "Invalid number of operands!");
1349 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001350 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1351 }
1352
1353 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1354 assert(N == 2 && "Invalid number of operands!");
1355 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1356 // The sign, shift type, and shift amount are encoded in a single operand
1357 // using the AM2 encoding helpers.
1358 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1359 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1360 PostIdxReg.ShiftTy);
1361 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001362 }
1363
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001364 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
1366 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1367 }
1368
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001369 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1370 assert(N == 1 && "Invalid number of operands!");
1371 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1372 }
1373
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001374 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1375 assert(N == 1 && "Invalid number of operands!");
1376 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1377 }
1378
1379 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1380 assert(N == 1 && "Invalid number of operands!");
1381 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1382 }
1383
1384 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1385 assert(N == 1 && "Invalid number of operands!");
1386 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1387 }
1388
Jim Grosbach602aa902011-07-13 15:34:57 +00001389 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001390
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001391 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001392 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001393 Op->ITMask.Mask = Mask;
1394 Op->StartLoc = S;
1395 Op->EndLoc = S;
1396 return Op;
1397 }
1398
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001399 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001400 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001401 Op->CC.Val = CC;
1402 Op->StartLoc = S;
1403 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001404 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001405 }
1406
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001407 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001408 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001409 Op->Cop.Val = CopVal;
1410 Op->StartLoc = S;
1411 Op->EndLoc = S;
1412 return Op;
1413 }
1414
1415 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001416 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001417 Op->Cop.Val = CopVal;
1418 Op->StartLoc = S;
1419 Op->EndLoc = S;
1420 return Op;
1421 }
1422
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001423 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001424 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001425 Op->Reg.RegNum = RegNum;
1426 Op->StartLoc = S;
1427 Op->EndLoc = S;
1428 return Op;
1429 }
1430
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001431 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001432 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001433 Op->Tok.Data = Str.data();
1434 Op->Tok.Length = Str.size();
1435 Op->StartLoc = S;
1436 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001437 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001438 }
1439
Bill Wendling2063b842010-11-18 23:43:05 +00001440 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001441 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001442 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001443 Op->StartLoc = S;
1444 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001445 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001446 }
1447
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001448 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1449 unsigned SrcReg,
1450 unsigned ShiftReg,
1451 unsigned ShiftImm,
1452 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001453 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001454 Op->RegShiftedReg.ShiftTy = ShTy;
1455 Op->RegShiftedReg.SrcReg = SrcReg;
1456 Op->RegShiftedReg.ShiftReg = ShiftReg;
1457 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001458 Op->StartLoc = S;
1459 Op->EndLoc = E;
1460 return Op;
1461 }
1462
Owen Andersonb595ed02011-07-21 18:54:16 +00001463 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1464 unsigned SrcReg,
1465 unsigned ShiftImm,
1466 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001467 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001468 Op->RegShiftedImm.ShiftTy = ShTy;
1469 Op->RegShiftedImm.SrcReg = SrcReg;
1470 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001471 Op->StartLoc = S;
1472 Op->EndLoc = E;
1473 return Op;
1474 }
1475
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001476 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001477 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001478 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001479 Op->ShifterImm.isASR = isASR;
1480 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001481 Op->StartLoc = S;
1482 Op->EndLoc = E;
1483 return Op;
1484 }
1485
Jim Grosbach833b9d32011-07-27 20:15:40 +00001486 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001487 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001488 Op->RotImm.Imm = Imm;
1489 Op->StartLoc = S;
1490 Op->EndLoc = E;
1491 return Op;
1492 }
1493
Jim Grosbach864b6092011-07-28 21:34:26 +00001494 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1495 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001496 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001497 Op->Bitfield.LSB = LSB;
1498 Op->Bitfield.Width = Width;
1499 Op->StartLoc = S;
1500 Op->EndLoc = E;
1501 return Op;
1502 }
1503
Bill Wendling2cae3272010-11-09 22:44:22 +00001504 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001505 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001506 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001507 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001508
Jim Grosbach75461af2011-09-13 22:56:44 +00001509 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001510 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001511 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001512 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001513 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001514
1515 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001516 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001517 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001518 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001519 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001520 Op->StartLoc = StartLoc;
1521 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001522 return Op;
1523 }
1524
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001525 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1526 MCContext &Ctx) {
1527 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1528 Op->VectorIndex.Val = Idx;
1529 Op->StartLoc = S;
1530 Op->EndLoc = E;
1531 return Op;
1532 }
1533
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001534 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001535 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001536 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001537 Op->StartLoc = S;
1538 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001539 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001540 }
1541
Jim Grosbache7fbce72011-10-03 23:38:36 +00001542 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001543 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00001544 Op->FPImm.Val = Val;
1545 Op->StartLoc = S;
1546 Op->EndLoc = S;
1547 return Op;
1548 }
1549
Jim Grosbachd3595712011-08-03 23:50:40 +00001550 static ARMOperand *CreateMem(unsigned BaseRegNum,
1551 const MCConstantExpr *OffsetImm,
1552 unsigned OffsetRegNum,
1553 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001554 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001555 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001556 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001557 ARMOperand *Op = new ARMOperand(k_Memory);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001558 Op->Mem.BaseRegNum = BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +00001559 Op->Mem.OffsetImm = OffsetImm;
1560 Op->Mem.OffsetRegNum = OffsetRegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001561 Op->Mem.ShiftType = ShiftType;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001562 Op->Mem.ShiftImm = ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +00001563 Op->Mem.isNegative = isNegative;
1564 Op->StartLoc = S;
1565 Op->EndLoc = E;
1566 return Op;
1567 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001568
Jim Grosbachc320c852011-08-05 21:28:30 +00001569 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1570 ARM_AM::ShiftOpc ShiftTy,
1571 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001572 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001573 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00001574 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00001575 Op->PostIdxReg.isAdd = isAdd;
1576 Op->PostIdxReg.ShiftTy = ShiftTy;
1577 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001578 Op->StartLoc = S;
1579 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001580 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001581 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001582
1583 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001584 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001585 Op->MBOpt.Val = Opt;
1586 Op->StartLoc = S;
1587 Op->EndLoc = S;
1588 return Op;
1589 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001590
1591 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001592 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001593 Op->IFlags.Val = IFlags;
1594 Op->StartLoc = S;
1595 Op->EndLoc = S;
1596 return Op;
1597 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001598
1599 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001600 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001601 Op->MMask.Val = MMask;
1602 Op->StartLoc = S;
1603 Op->EndLoc = S;
1604 return Op;
1605 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001606};
1607
1608} // end anonymous namespace.
1609
Jim Grosbach602aa902011-07-13 15:34:57 +00001610void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001611 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001612 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00001613 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1614 << ") >";
1615 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001616 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00001617 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001618 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001619 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001620 OS << "<ccout " << getReg() << ">";
1621 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001622 case k_ITCondMask: {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001623 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1624 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1625 "(tee)", "(eee)" };
1626 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1627 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1628 break;
1629 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001630 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001631 OS << "<coprocessor number: " << getCoproc() << ">";
1632 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001633 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001634 OS << "<coprocessor register: " << getCoproc() << ">";
1635 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001636 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001637 OS << "<mask: " << getMSRMask() << ">";
1638 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001639 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001640 getImm()->print(OS);
1641 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001642 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001643 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1644 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001645 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001646 OS << "<memory "
Jim Grosbachd3595712011-08-03 23:50:40 +00001647 << " base:" << Mem.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001648 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001649 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001650 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00001651 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1652 << PostIdxReg.RegNum;
1653 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1654 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1655 << PostIdxReg.ShiftImm;
1656 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00001657 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001658 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001659 OS << "<ARM_PROC::";
1660 unsigned IFlags = getProcIFlags();
1661 for (int i=2; i >= 0; --i)
1662 if (IFlags & (1 << i))
1663 OS << ARM_PROC::IFlagsToString(1 << i);
1664 OS << ">";
1665 break;
1666 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001667 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00001668 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001669 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001670 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001671 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1672 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001673 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001674 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00001675 OS << "<so_reg_reg "
Jim Grosbachac798e12011-07-25 20:49:51 +00001676 << RegShiftedReg.SrcReg
1677 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1678 << ", " << RegShiftedReg.ShiftReg << ", "
1679 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001680 << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001681 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001682 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00001683 OS << "<so_reg_imm "
Jim Grosbachac798e12011-07-25 20:49:51 +00001684 << RegShiftedImm.SrcReg
1685 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1686 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Andersonb595ed02011-07-21 18:54:16 +00001687 << ">";
1688 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001689 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00001690 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1691 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001692 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00001693 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1694 << ", width: " << Bitfield.Width << ">";
1695 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001696 case k_RegisterList:
1697 case k_DPRRegisterList:
1698 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00001699 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001700
Bill Wendlingbed94652010-11-09 23:28:44 +00001701 const SmallVectorImpl<unsigned> &RegList = getRegList();
1702 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001703 I = RegList.begin(), E = RegList.end(); I != E; ) {
1704 OS << *I;
1705 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001706 }
1707
1708 OS << ">";
1709 break;
1710 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001711 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001712 OS << "'" << getToken() << "'";
1713 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001714 case k_VectorIndex:
1715 OS << "<vectorindex " << getVectorIndex() << ">";
1716 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001717 }
1718}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001719
1720/// @name Auto-generated Match Functions
1721/// {
1722
1723static unsigned MatchRegisterName(StringRef Name);
1724
1725/// }
1726
Bob Wilsonfb0bd042011-02-03 21:46:10 +00001727bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1728 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001729 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00001730
1731 return (RegNo == (unsigned)-1);
1732}
1733
Kevin Enderby8be42bd2009-10-30 22:55:57 +00001734/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00001735/// and if it is a register name the token is eaten and the register number is
1736/// returned. Otherwise return -1.
1737///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001738int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00001739 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00001740 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00001741
Chris Lattner44e5981c2010-10-30 04:09:10 +00001742 // FIXME: Validate register for the current architecture; we have to do
1743 // validation later, so maybe there is no need for this here.
Owen Andersona098d152011-01-13 22:50:36 +00001744 std::string upperCase = Tok.getString().str();
1745 std::string lowerCase = LowercaseString(upperCase);
1746 unsigned RegNum = MatchRegisterName(lowerCase);
1747 if (!RegNum) {
1748 RegNum = StringSwitch<unsigned>(lowerCase)
1749 .Case("r13", ARM::SP)
1750 .Case("r14", ARM::LR)
1751 .Case("r15", ARM::PC)
1752 .Case("ip", ARM::R12)
1753 .Default(0);
1754 }
1755 if (!RegNum) return -1;
Bob Wilsonfb0bd042011-02-03 21:46:10 +00001756
Chris Lattner44e5981c2010-10-30 04:09:10 +00001757 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001758
1759#if 0
1760 // Also check for an index operand. This is only legal for vector registers,
1761 // but that'll get caught OK in operand matching, so we don't need to
1762 // explicitly filter everything else out here.
1763 if (Parser.getTok().is(AsmToken::LBrac)) {
1764 SMLoc SIdx = Parser.getTok().getLoc();
1765 Parser.Lex(); // Eat left bracket token.
1766
1767 const MCExpr *ImmVal;
1768 SMLoc ExprLoc = Parser.getTok().getLoc();
1769 if (getParser().ParseExpression(ImmVal))
1770 return MatchOperand_ParseFail;
1771 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1772 if (!MCE) {
1773 TokError("immediate value expected for vector index");
1774 return MatchOperand_ParseFail;
1775 }
1776
1777 SMLoc E = Parser.getTok().getLoc();
1778 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1779 Error(E, "']' expected");
1780 return MatchOperand_ParseFail;
1781 }
1782
1783 Parser.Lex(); // Eat right bracket token.
1784
1785 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1786 SIdx, E,
1787 getContext()));
1788 }
1789#endif
1790
Chris Lattner44e5981c2010-10-30 04:09:10 +00001791 return RegNum;
1792}
Jim Grosbach99710a82010-11-01 16:44:21 +00001793
Jim Grosbachbb24c592011-07-13 18:49:30 +00001794// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1795// If a recoverable error occurs, return 1. If an irrecoverable error
1796// occurs, return -1. An irrecoverable error is one where tokens have been
1797// consumed in the process of trying to parse the shifter (i.e., when it is
1798// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00001799int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001800 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1801 SMLoc S = Parser.getTok().getLoc();
1802 const AsmToken &Tok = Parser.getTok();
1803 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1804
1805 std::string upperCase = Tok.getString().str();
1806 std::string lowerCase = LowercaseString(upperCase);
1807 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1808 .Case("lsl", ARM_AM::lsl)
1809 .Case("lsr", ARM_AM::lsr)
1810 .Case("asr", ARM_AM::asr)
1811 .Case("ror", ARM_AM::ror)
1812 .Case("rrx", ARM_AM::rrx)
1813 .Default(ARM_AM::no_shift);
1814
1815 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00001816 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001817
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001818 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001819
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001820 // The source register for the shift has already been added to the
1821 // operand list, so we need to pop it off and combine it into the shifted
1822 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00001823 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001824 if (!PrevOp->isReg())
1825 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1826 int SrcReg = PrevOp->getReg();
1827 int64_t Imm = 0;
1828 int ShiftReg = 0;
1829 if (ShiftTy == ARM_AM::rrx) {
1830 // RRX Doesn't have an explicit shift amount. The encoder expects
1831 // the shift register to be the same as the source register. Seems odd,
1832 // but OK.
1833 ShiftReg = SrcReg;
1834 } else {
1835 // Figure out if this is shifted by a constant or a register (for non-RRX).
1836 if (Parser.getTok().is(AsmToken::Hash)) {
1837 Parser.Lex(); // Eat hash.
1838 SMLoc ImmLoc = Parser.getTok().getLoc();
1839 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00001840 if (getParser().ParseExpression(ShiftExpr)) {
1841 Error(ImmLoc, "invalid immediate shift value");
1842 return -1;
1843 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001844 // The expression must be evaluatable as an immediate.
1845 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00001846 if (!CE) {
1847 Error(ImmLoc, "invalid immediate shift value");
1848 return -1;
1849 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001850 // Range check the immediate.
1851 // lsl, ror: 0 <= imm <= 31
1852 // lsr, asr: 0 <= imm <= 32
1853 Imm = CE->getValue();
1854 if (Imm < 0 ||
1855 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
1856 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00001857 Error(ImmLoc, "immediate shift value out of range");
1858 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001859 }
1860 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001861 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001862 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00001863 if (ShiftReg == -1) {
1864 Error (L, "expected immediate or register in shift operand");
1865 return -1;
1866 }
1867 } else {
1868 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001869 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00001870 return -1;
1871 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001872 }
1873
Owen Andersonb595ed02011-07-21 18:54:16 +00001874 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1875 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00001876 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001877 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00001878 else
1879 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1880 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001881
Jim Grosbachbb24c592011-07-13 18:49:30 +00001882 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001883}
1884
1885
Bill Wendling2063b842010-11-18 23:43:05 +00001886/// Try to parse a register name. The token must be an Identifier when called.
1887/// If it's a register, an AsmOperand is created. Another AsmOperand is created
1888/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001889///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00001890/// TODO this is likely to change to allow different register types and or to
1891/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00001892bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001893tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00001894 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001895 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00001896 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00001897 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00001898
Bill Wendling2063b842010-11-18 23:43:05 +00001899 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001900
Chris Lattner44e5981c2010-10-30 04:09:10 +00001901 const AsmToken &ExclaimTok = Parser.getTok();
1902 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00001903 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
1904 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00001905 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001906 return false;
1907 }
1908
1909 // Also check for an index operand. This is only legal for vector registers,
1910 // but that'll get caught OK in operand matching, so we don't need to
1911 // explicitly filter everything else out here.
1912 if (Parser.getTok().is(AsmToken::LBrac)) {
1913 SMLoc SIdx = Parser.getTok().getLoc();
1914 Parser.Lex(); // Eat left bracket token.
1915
1916 const MCExpr *ImmVal;
1917 SMLoc ExprLoc = Parser.getTok().getLoc();
1918 if (getParser().ParseExpression(ImmVal))
1919 return MatchOperand_ParseFail;
1920 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1921 if (!MCE) {
1922 TokError("immediate value expected for vector index");
1923 return MatchOperand_ParseFail;
1924 }
1925
1926 SMLoc E = Parser.getTok().getLoc();
1927 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1928 Error(E, "']' expected");
1929 return MatchOperand_ParseFail;
1930 }
1931
1932 Parser.Lex(); // Eat right bracket token.
1933
1934 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1935 SIdx, E,
1936 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00001937 }
1938
Bill Wendling2063b842010-11-18 23:43:05 +00001939 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001940}
1941
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001942/// MatchCoprocessorOperandName - Try to parse an coprocessor related
1943/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
1944/// "c5", ...
1945static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001946 // Use the same layout as the tablegen'erated register name matcher. Ugly,
1947 // but efficient.
1948 switch (Name.size()) {
1949 default: break;
1950 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001951 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001952 return -1;
1953 switch (Name[1]) {
1954 default: return -1;
1955 case '0': return 0;
1956 case '1': return 1;
1957 case '2': return 2;
1958 case '3': return 3;
1959 case '4': return 4;
1960 case '5': return 5;
1961 case '6': return 6;
1962 case '7': return 7;
1963 case '8': return 8;
1964 case '9': return 9;
1965 }
1966 break;
1967 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001968 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001969 return -1;
1970 switch (Name[2]) {
1971 default: return -1;
1972 case '0': return 10;
1973 case '1': return 11;
1974 case '2': return 12;
1975 case '3': return 13;
1976 case '4': return 14;
1977 case '5': return 15;
1978 }
1979 break;
1980 }
1981
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001982 return -1;
1983}
1984
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001985/// parseITCondCode - Try to parse a condition code for an IT instruction.
1986ARMAsmParser::OperandMatchResultTy ARMAsmParser::
1987parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1988 SMLoc S = Parser.getTok().getLoc();
1989 const AsmToken &Tok = Parser.getTok();
1990 if (!Tok.is(AsmToken::Identifier))
1991 return MatchOperand_NoMatch;
1992 unsigned CC = StringSwitch<unsigned>(Tok.getString())
1993 .Case("eq", ARMCC::EQ)
1994 .Case("ne", ARMCC::NE)
1995 .Case("hs", ARMCC::HS)
1996 .Case("cs", ARMCC::HS)
1997 .Case("lo", ARMCC::LO)
1998 .Case("cc", ARMCC::LO)
1999 .Case("mi", ARMCC::MI)
2000 .Case("pl", ARMCC::PL)
2001 .Case("vs", ARMCC::VS)
2002 .Case("vc", ARMCC::VC)
2003 .Case("hi", ARMCC::HI)
2004 .Case("ls", ARMCC::LS)
2005 .Case("ge", ARMCC::GE)
2006 .Case("lt", ARMCC::LT)
2007 .Case("gt", ARMCC::GT)
2008 .Case("le", ARMCC::LE)
2009 .Case("al", ARMCC::AL)
2010 .Default(~0U);
2011 if (CC == ~0U)
2012 return MatchOperand_NoMatch;
2013 Parser.Lex(); // Eat the token.
2014
2015 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2016
2017 return MatchOperand_Success;
2018}
2019
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002020/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002021/// token must be an Identifier when called, and if it is a coprocessor
2022/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002023ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002024parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002025 SMLoc S = Parser.getTok().getLoc();
2026 const AsmToken &Tok = Parser.getTok();
2027 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2028
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002029 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002030 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002031 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002032
2033 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002034 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002035 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002036}
2037
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002038/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002039/// token must be an Identifier when called, and if it is a coprocessor
2040/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002041ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002042parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002043 SMLoc S = Parser.getTok().getLoc();
2044 const AsmToken &Tok = Parser.getTok();
2045 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2046
2047 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2048 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002049 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002050
2051 Parser.Lex(); // Eat identifier token.
2052 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002053 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002054}
2055
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002056// For register list parsing, we need to map from raw GPR register numbering
2057// to the enumeration values. The enumeration values aren't sorted by
2058// register number due to our using "sp", "lr" and "pc" as canonical names.
2059static unsigned getNextRegister(unsigned Reg) {
2060 // If this is a GPR, we need to do it manually, otherwise we can rely
2061 // on the sort ordering of the enumeration since the other reg-classes
2062 // are sane.
2063 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2064 return Reg + 1;
2065 switch(Reg) {
2066 default: assert(0 && "Invalid GPR number!");
2067 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2068 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2069 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2070 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2071 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2072 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2073 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2074 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2075 }
2076}
2077
2078/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002079bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002080parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002081 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002082 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002083 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002084 Parser.Lex(); // Eat '{' token.
2085 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002086
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002087 // Check the first register in the list to see what register class
2088 // this is a list of.
2089 int Reg = tryParseRegister();
2090 if (Reg == -1)
2091 return Error(RegLoc, "register expected");
2092
2093 MCRegisterClass *RC;
2094 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2095 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2096 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2097 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2098 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2099 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2100 else
2101 return Error(RegLoc, "invalid register in register list");
2102
2103 // The reglist instructions have at most 16 registers, so reserve
2104 // space for that many.
Jim Grosbache3a6a822011-09-13 20:35:57 +00002105 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002106 // Store the first register.
2107 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002108
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002109 // This starts immediately after the first register token in the list,
2110 // so we can see either a comma or a minus (range separator) as a legal
2111 // next token.
2112 while (Parser.getTok().is(AsmToken::Comma) ||
2113 Parser.getTok().is(AsmToken::Minus)) {
2114 if (Parser.getTok().is(AsmToken::Minus)) {
2115 Parser.Lex(); // Eat the comma.
2116 SMLoc EndLoc = Parser.getTok().getLoc();
2117 int EndReg = tryParseRegister();
2118 if (EndReg == -1)
2119 return Error(EndLoc, "register expected");
2120 // If the register is the same as the start reg, there's nothing
2121 // more to do.
2122 if (Reg == EndReg)
2123 continue;
2124 // The register must be in the same register class as the first.
2125 if (!RC->contains(EndReg))
2126 return Error(EndLoc, "invalid register in register list");
2127 // Ranges must go from low to high.
2128 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2129 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002130
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002131 // Add all the registers in the range to the register list.
2132 while (Reg != EndReg) {
2133 Reg = getNextRegister(Reg);
2134 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2135 }
2136 continue;
2137 }
2138 Parser.Lex(); // Eat the comma.
2139 RegLoc = Parser.getTok().getLoc();
2140 int OldReg = Reg;
2141 Reg = tryParseRegister();
2142 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002143 return Error(RegLoc, "register expected");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002144 // The register must be in the same register class as the first.
2145 if (!RC->contains(Reg))
2146 return Error(RegLoc, "invalid register in register list");
2147 // List must be monotonically increasing.
2148 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2149 return Error(RegLoc, "register list not in ascending order");
2150 // VFP register lists must also be contiguous.
2151 // It's OK to use the enumeration values directly here rather, as the
2152 // VFP register classes have the enum sorted properly.
2153 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2154 Reg != OldReg + 1)
2155 return Error(RegLoc, "non-contiguous register range");
2156 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002157 }
2158
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002159 SMLoc E = Parser.getTok().getLoc();
2160 if (Parser.getTok().isNot(AsmToken::RCurly))
2161 return Error(E, "'}' expected");
2162 Parser.Lex(); // Eat '}' token.
2163
Bill Wendling2063b842010-11-18 23:43:05 +00002164 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2165 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002166}
2167
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002168/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002169ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002170parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002171 SMLoc S = Parser.getTok().getLoc();
2172 const AsmToken &Tok = Parser.getTok();
2173 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2174 StringRef OptStr = Tok.getString();
2175
2176 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2177 .Case("sy", ARM_MB::SY)
2178 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002179 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002180 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002181 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002182 .Case("ishst", ARM_MB::ISHST)
2183 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002184 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002185 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002186 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002187 .Case("osh", ARM_MB::OSH)
2188 .Case("oshst", ARM_MB::OSHST)
2189 .Default(~0U);
2190
2191 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002192 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002193
2194 Parser.Lex(); // Eat identifier token.
2195 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002196 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002197}
2198
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002199/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002200ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002201parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002202 SMLoc S = Parser.getTok().getLoc();
2203 const AsmToken &Tok = Parser.getTok();
2204 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2205 StringRef IFlagsStr = Tok.getString();
2206
Owen Anderson10c5b122011-10-05 17:16:40 +00002207 // An iflags string of "none" is interpreted to mean that none of the AIF
2208 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002209 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00002210 if (IFlagsStr != "none") {
2211 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2212 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2213 .Case("a", ARM_PROC::A)
2214 .Case("i", ARM_PROC::I)
2215 .Case("f", ARM_PROC::F)
2216 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002217
Owen Anderson10c5b122011-10-05 17:16:40 +00002218 // If some specific iflag is already set, it means that some letter is
2219 // present more than once, this is not acceptable.
2220 if (Flag == ~0U || (IFlags & Flag))
2221 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002222
Owen Anderson10c5b122011-10-05 17:16:40 +00002223 IFlags |= Flag;
2224 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002225 }
2226
2227 Parser.Lex(); // Eat identifier token.
2228 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2229 return MatchOperand_Success;
2230}
2231
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002232/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002233ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002234parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002235 SMLoc S = Parser.getTok().getLoc();
2236 const AsmToken &Tok = Parser.getTok();
2237 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2238 StringRef Mask = Tok.getString();
2239
James Molloy21efa7d2011-09-28 14:21:38 +00002240 if (isMClass()) {
2241 // See ARMv6-M 10.1.1
2242 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2243 .Case("apsr", 0)
2244 .Case("iapsr", 1)
2245 .Case("eapsr", 2)
2246 .Case("xpsr", 3)
2247 .Case("ipsr", 5)
2248 .Case("epsr", 6)
2249 .Case("iepsr", 7)
2250 .Case("msp", 8)
2251 .Case("psp", 9)
2252 .Case("primask", 16)
2253 .Case("basepri", 17)
2254 .Case("basepri_max", 18)
2255 .Case("faultmask", 19)
2256 .Case("control", 20)
2257 .Default(~0U);
2258
2259 if (FlagsVal == ~0U)
2260 return MatchOperand_NoMatch;
2261
2262 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2263 // basepri, basepri_max and faultmask only valid for V7m.
2264 return MatchOperand_NoMatch;
2265
2266 Parser.Lex(); // Eat identifier token.
2267 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2268 return MatchOperand_Success;
2269 }
2270
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002271 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2272 size_t Start = 0, Next = Mask.find('_');
2273 StringRef Flags = "";
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002274 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002275 if (Next != StringRef::npos)
2276 Flags = Mask.slice(Next+1, Mask.size());
2277
2278 // FlagsVal contains the complete mask:
2279 // 3-0: Mask
2280 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2281 unsigned FlagsVal = 0;
2282
2283 if (SpecReg == "apsr") {
2284 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002285 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002286 .Case("g", 0x4) // same as CPSR_s
2287 .Case("nzcvqg", 0xc) // same as CPSR_fs
2288 .Default(~0U);
2289
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002290 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002291 if (!Flags.empty())
2292 return MatchOperand_NoMatch;
2293 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00002294 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002295 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002296 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00002297 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2298 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002299 for (int i = 0, e = Flags.size(); i != e; ++i) {
2300 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2301 .Case("c", 1)
2302 .Case("x", 2)
2303 .Case("s", 4)
2304 .Case("f", 8)
2305 .Default(~0U);
2306
2307 // If some specific flag is already set, it means that some letter is
2308 // present more than once, this is not acceptable.
2309 if (FlagsVal == ~0U || (FlagsVal & Flag))
2310 return MatchOperand_NoMatch;
2311 FlagsVal |= Flag;
2312 }
2313 } else // No match for special register.
2314 return MatchOperand_NoMatch;
2315
2316 // Special register without flags are equivalent to "fc" flags.
2317 if (!FlagsVal)
2318 FlagsVal = 0x9;
2319
2320 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2321 if (SpecReg == "spsr")
2322 FlagsVal |= 16;
2323
2324 Parser.Lex(); // Eat identifier token.
2325 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2326 return MatchOperand_Success;
2327}
2328
Jim Grosbach27c1e252011-07-21 17:23:04 +00002329ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2330parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2331 int Low, int High) {
2332 const AsmToken &Tok = Parser.getTok();
2333 if (Tok.isNot(AsmToken::Identifier)) {
2334 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2335 return MatchOperand_ParseFail;
2336 }
2337 StringRef ShiftName = Tok.getString();
2338 std::string LowerOp = LowercaseString(Op);
2339 std::string UpperOp = UppercaseString(Op);
2340 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2341 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2342 return MatchOperand_ParseFail;
2343 }
2344 Parser.Lex(); // Eat shift type token.
2345
2346 // There must be a '#' and a shift amount.
2347 if (Parser.getTok().isNot(AsmToken::Hash)) {
2348 Error(Parser.getTok().getLoc(), "'#' expected");
2349 return MatchOperand_ParseFail;
2350 }
2351 Parser.Lex(); // Eat hash token.
2352
2353 const MCExpr *ShiftAmount;
2354 SMLoc Loc = Parser.getTok().getLoc();
2355 if (getParser().ParseExpression(ShiftAmount)) {
2356 Error(Loc, "illegal expression");
2357 return MatchOperand_ParseFail;
2358 }
2359 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2360 if (!CE) {
2361 Error(Loc, "constant expression expected");
2362 return MatchOperand_ParseFail;
2363 }
2364 int Val = CE->getValue();
2365 if (Val < Low || Val > High) {
2366 Error(Loc, "immediate value out of range");
2367 return MatchOperand_ParseFail;
2368 }
2369
2370 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2371
2372 return MatchOperand_Success;
2373}
2374
Jim Grosbach0a547702011-07-22 17:44:50 +00002375ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2376parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2377 const AsmToken &Tok = Parser.getTok();
2378 SMLoc S = Tok.getLoc();
2379 if (Tok.isNot(AsmToken::Identifier)) {
2380 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2381 return MatchOperand_ParseFail;
2382 }
2383 int Val = StringSwitch<int>(Tok.getString())
2384 .Case("be", 1)
2385 .Case("le", 0)
2386 .Default(-1);
2387 Parser.Lex(); // Eat the token.
2388
2389 if (Val == -1) {
2390 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2391 return MatchOperand_ParseFail;
2392 }
2393 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2394 getContext()),
2395 S, Parser.getTok().getLoc()));
2396 return MatchOperand_Success;
2397}
2398
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002399/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2400/// instructions. Legal values are:
2401/// lsl #n 'n' in [0,31]
2402/// asr #n 'n' in [1,32]
2403/// n == 32 encoded as n == 0.
2404ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2405parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2406 const AsmToken &Tok = Parser.getTok();
2407 SMLoc S = Tok.getLoc();
2408 if (Tok.isNot(AsmToken::Identifier)) {
2409 Error(S, "shift operator 'asr' or 'lsl' expected");
2410 return MatchOperand_ParseFail;
2411 }
2412 StringRef ShiftName = Tok.getString();
2413 bool isASR;
2414 if (ShiftName == "lsl" || ShiftName == "LSL")
2415 isASR = false;
2416 else if (ShiftName == "asr" || ShiftName == "ASR")
2417 isASR = true;
2418 else {
2419 Error(S, "shift operator 'asr' or 'lsl' expected");
2420 return MatchOperand_ParseFail;
2421 }
2422 Parser.Lex(); // Eat the operator.
2423
2424 // A '#' and a shift amount.
2425 if (Parser.getTok().isNot(AsmToken::Hash)) {
2426 Error(Parser.getTok().getLoc(), "'#' expected");
2427 return MatchOperand_ParseFail;
2428 }
2429 Parser.Lex(); // Eat hash token.
2430
2431 const MCExpr *ShiftAmount;
2432 SMLoc E = Parser.getTok().getLoc();
2433 if (getParser().ParseExpression(ShiftAmount)) {
2434 Error(E, "malformed shift expression");
2435 return MatchOperand_ParseFail;
2436 }
2437 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2438 if (!CE) {
2439 Error(E, "shift amount must be an immediate");
2440 return MatchOperand_ParseFail;
2441 }
2442
2443 int64_t Val = CE->getValue();
2444 if (isASR) {
2445 // Shift amount must be in [1,32]
2446 if (Val < 1 || Val > 32) {
2447 Error(E, "'asr' shift amount must be in range [1,32]");
2448 return MatchOperand_ParseFail;
2449 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00002450 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2451 if (isThumb() && Val == 32) {
2452 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2453 return MatchOperand_ParseFail;
2454 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002455 if (Val == 32) Val = 0;
2456 } else {
2457 // Shift amount must be in [1,32]
2458 if (Val < 0 || Val > 31) {
2459 Error(E, "'lsr' shift amount must be in range [0,31]");
2460 return MatchOperand_ParseFail;
2461 }
2462 }
2463
2464 E = Parser.getTok().getLoc();
2465 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2466
2467 return MatchOperand_Success;
2468}
2469
Jim Grosbach833b9d32011-07-27 20:15:40 +00002470/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2471/// of instructions. Legal values are:
2472/// ror #n 'n' in {0, 8, 16, 24}
2473ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2474parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2475 const AsmToken &Tok = Parser.getTok();
2476 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00002477 if (Tok.isNot(AsmToken::Identifier))
2478 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002479 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00002480 if (ShiftName != "ror" && ShiftName != "ROR")
2481 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002482 Parser.Lex(); // Eat the operator.
2483
2484 // A '#' and a rotate amount.
2485 if (Parser.getTok().isNot(AsmToken::Hash)) {
2486 Error(Parser.getTok().getLoc(), "'#' expected");
2487 return MatchOperand_ParseFail;
2488 }
2489 Parser.Lex(); // Eat hash token.
2490
2491 const MCExpr *ShiftAmount;
2492 SMLoc E = Parser.getTok().getLoc();
2493 if (getParser().ParseExpression(ShiftAmount)) {
2494 Error(E, "malformed rotate expression");
2495 return MatchOperand_ParseFail;
2496 }
2497 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2498 if (!CE) {
2499 Error(E, "rotate amount must be an immediate");
2500 return MatchOperand_ParseFail;
2501 }
2502
2503 int64_t Val = CE->getValue();
2504 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2505 // normally, zero is represented in asm by omitting the rotate operand
2506 // entirely.
2507 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2508 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2509 return MatchOperand_ParseFail;
2510 }
2511
2512 E = Parser.getTok().getLoc();
2513 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2514
2515 return MatchOperand_Success;
2516}
2517
Jim Grosbach864b6092011-07-28 21:34:26 +00002518ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2519parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2520 SMLoc S = Parser.getTok().getLoc();
2521 // The bitfield descriptor is really two operands, the LSB and the width.
2522 if (Parser.getTok().isNot(AsmToken::Hash)) {
2523 Error(Parser.getTok().getLoc(), "'#' expected");
2524 return MatchOperand_ParseFail;
2525 }
2526 Parser.Lex(); // Eat hash token.
2527
2528 const MCExpr *LSBExpr;
2529 SMLoc E = Parser.getTok().getLoc();
2530 if (getParser().ParseExpression(LSBExpr)) {
2531 Error(E, "malformed immediate expression");
2532 return MatchOperand_ParseFail;
2533 }
2534 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2535 if (!CE) {
2536 Error(E, "'lsb' operand must be an immediate");
2537 return MatchOperand_ParseFail;
2538 }
2539
2540 int64_t LSB = CE->getValue();
2541 // The LSB must be in the range [0,31]
2542 if (LSB < 0 || LSB > 31) {
2543 Error(E, "'lsb' operand must be in the range [0,31]");
2544 return MatchOperand_ParseFail;
2545 }
2546 E = Parser.getTok().getLoc();
2547
2548 // Expect another immediate operand.
2549 if (Parser.getTok().isNot(AsmToken::Comma)) {
2550 Error(Parser.getTok().getLoc(), "too few operands");
2551 return MatchOperand_ParseFail;
2552 }
2553 Parser.Lex(); // Eat hash token.
2554 if (Parser.getTok().isNot(AsmToken::Hash)) {
2555 Error(Parser.getTok().getLoc(), "'#' expected");
2556 return MatchOperand_ParseFail;
2557 }
2558 Parser.Lex(); // Eat hash token.
2559
2560 const MCExpr *WidthExpr;
2561 if (getParser().ParseExpression(WidthExpr)) {
2562 Error(E, "malformed immediate expression");
2563 return MatchOperand_ParseFail;
2564 }
2565 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2566 if (!CE) {
2567 Error(E, "'width' operand must be an immediate");
2568 return MatchOperand_ParseFail;
2569 }
2570
2571 int64_t Width = CE->getValue();
2572 // The LSB must be in the range [1,32-lsb]
2573 if (Width < 1 || Width > 32 - LSB) {
2574 Error(E, "'width' operand must be in the range [1,32-lsb]");
2575 return MatchOperand_ParseFail;
2576 }
2577 E = Parser.getTok().getLoc();
2578
2579 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2580
2581 return MatchOperand_Success;
2582}
2583
Jim Grosbachd3595712011-08-03 23:50:40 +00002584ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2585parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2586 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00002587 // postidx_reg := '+' register {, shift}
2588 // | '-' register {, shift}
2589 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00002590
2591 // This method must return MatchOperand_NoMatch without consuming any tokens
2592 // in the case where there is no match, as other alternatives take other
2593 // parse methods.
2594 AsmToken Tok = Parser.getTok();
2595 SMLoc S = Tok.getLoc();
2596 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00002597 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00002598 int Reg = -1;
2599 if (Tok.is(AsmToken::Plus)) {
2600 Parser.Lex(); // Eat the '+' token.
2601 haveEaten = true;
2602 } else if (Tok.is(AsmToken::Minus)) {
2603 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00002604 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00002605 haveEaten = true;
2606 }
2607 if (Parser.getTok().is(AsmToken::Identifier))
2608 Reg = tryParseRegister();
2609 if (Reg == -1) {
2610 if (!haveEaten)
2611 return MatchOperand_NoMatch;
2612 Error(Parser.getTok().getLoc(), "register expected");
2613 return MatchOperand_ParseFail;
2614 }
2615 SMLoc E = Parser.getTok().getLoc();
2616
Jim Grosbachc320c852011-08-05 21:28:30 +00002617 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2618 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002619 if (Parser.getTok().is(AsmToken::Comma)) {
2620 Parser.Lex(); // Eat the ','.
2621 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2622 return MatchOperand_ParseFail;
2623 }
Jim Grosbachc320c852011-08-05 21:28:30 +00002624
2625 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2626 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00002627
2628 return MatchOperand_Success;
2629}
2630
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00002631ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2632parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2633 // Check for a post-index addressing register operand. Specifically:
2634 // am3offset := '+' register
2635 // | '-' register
2636 // | register
2637 // | # imm
2638 // | # + imm
2639 // | # - imm
2640
2641 // This method must return MatchOperand_NoMatch without consuming any tokens
2642 // in the case where there is no match, as other alternatives take other
2643 // parse methods.
2644 AsmToken Tok = Parser.getTok();
2645 SMLoc S = Tok.getLoc();
2646
2647 // Do immediates first, as we always parse those if we have a '#'.
2648 if (Parser.getTok().is(AsmToken::Hash)) {
2649 Parser.Lex(); // Eat the '#'.
2650 // Explicitly look for a '-', as we need to encode negative zero
2651 // differently.
2652 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2653 const MCExpr *Offset;
2654 if (getParser().ParseExpression(Offset))
2655 return MatchOperand_ParseFail;
2656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2657 if (!CE) {
2658 Error(S, "constant expression expected");
2659 return MatchOperand_ParseFail;
2660 }
2661 SMLoc E = Tok.getLoc();
2662 // Negative zero is encoded as the flag value INT32_MIN.
2663 int32_t Val = CE->getValue();
2664 if (isNegative && Val == 0)
2665 Val = INT32_MIN;
2666
2667 Operands.push_back(
2668 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2669
2670 return MatchOperand_Success;
2671 }
2672
2673
2674 bool haveEaten = false;
2675 bool isAdd = true;
2676 int Reg = -1;
2677 if (Tok.is(AsmToken::Plus)) {
2678 Parser.Lex(); // Eat the '+' token.
2679 haveEaten = true;
2680 } else if (Tok.is(AsmToken::Minus)) {
2681 Parser.Lex(); // Eat the '-' token.
2682 isAdd = false;
2683 haveEaten = true;
2684 }
2685 if (Parser.getTok().is(AsmToken::Identifier))
2686 Reg = tryParseRegister();
2687 if (Reg == -1) {
2688 if (!haveEaten)
2689 return MatchOperand_NoMatch;
2690 Error(Parser.getTok().getLoc(), "register expected");
2691 return MatchOperand_ParseFail;
2692 }
2693 SMLoc E = Parser.getTok().getLoc();
2694
2695 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2696 0, S, E));
2697
2698 return MatchOperand_Success;
2699}
2700
Jim Grosbach7db8d692011-09-08 22:07:06 +00002701/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2702/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2703/// when they refer multiple MIOperands inside a single one.
2704bool ARMAsmParser::
2705cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2706 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2707 // Rt, Rt2
2708 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2709 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2710 // Create a writeback register dummy placeholder.
2711 Inst.addOperand(MCOperand::CreateReg(0));
2712 // addr
2713 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2714 // pred
2715 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2716 return true;
2717}
2718
2719/// cvtT2StrdPre - Convert parsed operands to MCInst.
2720/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2721/// when they refer multiple MIOperands inside a single one.
2722bool ARMAsmParser::
2723cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2724 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2725 // Create a writeback register dummy placeholder.
2726 Inst.addOperand(MCOperand::CreateReg(0));
2727 // Rt, Rt2
2728 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2729 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2730 // addr
2731 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2732 // pred
2733 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2734 return true;
2735}
2736
Jim Grosbachc086f682011-09-08 00:39:19 +00002737/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2738/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2739/// when they refer multiple MIOperands inside a single one.
2740bool ARMAsmParser::
2741cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2742 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2743 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2744
2745 // Create a writeback register dummy placeholder.
2746 Inst.addOperand(MCOperand::CreateImm(0));
2747
2748 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2749 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2750 return true;
2751}
2752
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00002753/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2754/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2755/// when they refer multiple MIOperands inside a single one.
2756bool ARMAsmParser::
2757cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2758 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2759 // Create a writeback register dummy placeholder.
2760 Inst.addOperand(MCOperand::CreateImm(0));
2761 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2762 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2763 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2764 return true;
2765}
2766
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002767/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002768/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2769/// when they refer multiple MIOperands inside a single one.
2770bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002771cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002772 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2773 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2774
2775 // Create a writeback register dummy placeholder.
2776 Inst.addOperand(MCOperand::CreateImm(0));
2777
Jim Grosbachd3595712011-08-03 23:50:40 +00002778 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002779 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2780 return true;
2781}
2782
Owen Anderson16d33f32011-08-26 20:43:14 +00002783/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2784/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2785/// when they refer multiple MIOperands inside a single one.
2786bool ARMAsmParser::
2787cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2788 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2789 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2790
2791 // Create a writeback register dummy placeholder.
2792 Inst.addOperand(MCOperand::CreateImm(0));
2793
2794 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2795 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2796 return true;
2797}
2798
2799
Jim Grosbachd564bf32011-08-11 19:22:40 +00002800/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2801/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2802/// when they refer multiple MIOperands inside a single one.
2803bool ARMAsmParser::
2804cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2805 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2806 // Create a writeback register dummy placeholder.
2807 Inst.addOperand(MCOperand::CreateImm(0));
2808 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2809 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2810 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2811 return true;
2812}
2813
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002814/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002815/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2816/// when they refer multiple MIOperands inside a single one.
2817bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002818cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002819 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2820 // Create a writeback register dummy placeholder.
2821 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00002822 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2823 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2824 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00002825 return true;
2826}
2827
Jim Grosbachd886f8c2011-08-11 21:17:22 +00002828/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2829/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2830/// when they refer multiple MIOperands inside a single one.
2831bool ARMAsmParser::
2832cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2833 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2834 // Create a writeback register dummy placeholder.
2835 Inst.addOperand(MCOperand::CreateImm(0));
2836 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2837 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2838 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2839 return true;
2840}
2841
Jim Grosbachd3595712011-08-03 23:50:40 +00002842/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2843/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2844/// when they refer multiple MIOperands inside a single one.
2845bool ARMAsmParser::
2846cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2847 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2848 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002849 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00002850 // Create a writeback register dummy placeholder.
2851 Inst.addOperand(MCOperand::CreateImm(0));
2852 // addr
2853 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2854 // offset
2855 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2856 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002857 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2858 return true;
2859}
2860
Jim Grosbachd3595712011-08-03 23:50:40 +00002861/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002862/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2863/// when they refer multiple MIOperands inside a single one.
2864bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00002865cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2866 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2867 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00002868 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002869 // Create a writeback register dummy placeholder.
2870 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00002871 // addr
2872 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2873 // offset
2874 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2875 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002876 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2877 return true;
2878}
2879
Jim Grosbachd3595712011-08-03 23:50:40 +00002880/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002881/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2882/// when they refer multiple MIOperands inside a single one.
2883bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00002884cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2885 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002886 // Create a writeback register dummy placeholder.
2887 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00002888 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002889 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00002890 // addr
2891 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2892 // offset
2893 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2894 // pred
2895 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2896 return true;
2897}
2898
2899/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
2900/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2901/// when they refer multiple MIOperands inside a single one.
2902bool ARMAsmParser::
2903cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2904 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2905 // Create a writeback register dummy placeholder.
2906 Inst.addOperand(MCOperand::CreateImm(0));
2907 // Rt
2908 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2909 // addr
2910 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2911 // offset
2912 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2913 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002914 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2915 return true;
2916}
2917
Jim Grosbach5b96b802011-08-10 20:29:19 +00002918/// cvtLdrdPre - Convert parsed operands to MCInst.
2919/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2920/// when they refer multiple MIOperands inside a single one.
2921bool ARMAsmParser::
2922cvtLdrdPre(MCInst &Inst, unsigned Opcode,
2923 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2924 // Rt, Rt2
2925 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2926 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2927 // Create a writeback register dummy placeholder.
2928 Inst.addOperand(MCOperand::CreateImm(0));
2929 // addr
2930 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2931 // pred
2932 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2933 return true;
2934}
2935
Jim Grosbacheb09f492011-08-11 20:28:23 +00002936/// cvtStrdPre - Convert parsed operands to MCInst.
2937/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2938/// when they refer multiple MIOperands inside a single one.
2939bool ARMAsmParser::
2940cvtStrdPre(MCInst &Inst, unsigned Opcode,
2941 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2942 // Create a writeback register dummy placeholder.
2943 Inst.addOperand(MCOperand::CreateImm(0));
2944 // Rt, Rt2
2945 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2946 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2947 // addr
2948 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2949 // pred
2950 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2951 return true;
2952}
2953
Jim Grosbachcd4dd252011-08-10 22:42:16 +00002954/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2955/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2956/// when they refer multiple MIOperands inside a single one.
2957bool ARMAsmParser::
2958cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2959 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2960 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2961 // Create a writeback register dummy placeholder.
2962 Inst.addOperand(MCOperand::CreateImm(0));
2963 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2964 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2965 return true;
2966}
2967
Jim Grosbach8e048492011-08-19 22:07:46 +00002968/// cvtThumbMultiple- Convert parsed operands to MCInst.
2969/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2970/// when they refer multiple MIOperands inside a single one.
2971bool ARMAsmParser::
2972cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
2973 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2974 // The second source operand must be the same register as the destination
2975 // operand.
2976 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00002977 (((ARMOperand*)Operands[3])->getReg() !=
2978 ((ARMOperand*)Operands[5])->getReg()) &&
2979 (((ARMOperand*)Operands[3])->getReg() !=
2980 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00002981 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00002982 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00002983 return false;
2984 }
2985 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2986 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
2987 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach459422d2011-08-19 22:30:46 +00002988 // If we have a three-operand form, use that, else the second source operand
2989 // is just the destination operand again.
2990 if (Operands.size() == 6)
2991 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
2992 else
2993 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00002994 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
2995
2996 return true;
2997}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00002998
Bill Wendlinge18980a2010-11-06 22:36:58 +00002999/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003000/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003001bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003002parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003003 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003004 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003005 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003006 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003007 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003008
Sean Callanan936b0d32010-01-19 21:44:56 +00003009 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003010 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003011 if (BaseRegNum == -1)
3012 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003013
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003014 // The next token must either be a comma or a closing bracket.
3015 const AsmToken &Tok = Parser.getTok();
3016 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003017 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003018
Jim Grosbachd3595712011-08-03 23:50:40 +00003019 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003020 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003021 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003022
Jim Grosbachd3595712011-08-03 23:50:40 +00003023 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
3024 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003025
Jim Grosbach40700e02011-09-19 18:42:21 +00003026 // If there's a pre-indexing writeback marker, '!', just add it as a token
3027 // operand. It's rather odd, but syntactically valid.
3028 if (Parser.getTok().is(AsmToken::Exclaim)) {
3029 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3030 Parser.Lex(); // Eat the '!'.
3031 }
3032
Jim Grosbachd3595712011-08-03 23:50:40 +00003033 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003034 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003035
Jim Grosbachd3595712011-08-03 23:50:40 +00003036 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3037 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003038
Jim Grosbachd3595712011-08-03 23:50:40 +00003039 // If we have a '#' it's an immediate offset, else assume it's a register
3040 // offset.
3041 if (Parser.getTok().is(AsmToken::Hash)) {
3042 Parser.Lex(); // Eat the '#'.
3043 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003044
Owen Anderson967674d2011-08-29 19:36:44 +00003045 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003046 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003047 if (getParser().ParseExpression(Offset))
3048 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003049
3050 // The expression has to be a constant. Memory references with relocations
3051 // don't come through here, as they use the <label> forms of the relevant
3052 // instructions.
3053 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3054 if (!CE)
3055 return Error (E, "constant expression expected");
3056
Owen Anderson967674d2011-08-29 19:36:44 +00003057 // If the constant was #-0, represent it as INT32_MIN.
3058 int32_t Val = CE->getValue();
3059 if (isNegative && Val == 0)
3060 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3061
Jim Grosbachd3595712011-08-03 23:50:40 +00003062 // Now we should have the closing ']'
3063 E = Parser.getTok().getLoc();
3064 if (Parser.getTok().isNot(AsmToken::RBrac))
3065 return Error(E, "']' expected");
3066 Parser.Lex(); // Eat right bracket token.
3067
3068 // Don't worry about range checking the value here. That's handled by
3069 // the is*() predicates.
3070 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
3071 ARM_AM::no_shift, 0, false, S,E));
3072
3073 // If there's a pre-indexing writeback marker, '!', just add it as a token
3074 // operand.
3075 if (Parser.getTok().is(AsmToken::Exclaim)) {
3076 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3077 Parser.Lex(); // Eat the '!'.
3078 }
3079
3080 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003081 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003082
3083 // The register offset is optionally preceded by a '+' or '-'
3084 bool isNegative = false;
3085 if (Parser.getTok().is(AsmToken::Minus)) {
3086 isNegative = true;
3087 Parser.Lex(); // Eat the '-'.
3088 } else if (Parser.getTok().is(AsmToken::Plus)) {
3089 // Nothing to do.
3090 Parser.Lex(); // Eat the '+'.
3091 }
3092
3093 E = Parser.getTok().getLoc();
3094 int OffsetRegNum = tryParseRegister();
3095 if (OffsetRegNum == -1)
3096 return Error(E, "register expected");
3097
3098 // If there's a shift operator, handle it.
3099 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003100 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00003101 if (Parser.getTok().is(AsmToken::Comma)) {
3102 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003103 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00003104 return true;
3105 }
3106
3107 // Now we should have the closing ']'
3108 E = Parser.getTok().getLoc();
3109 if (Parser.getTok().isNot(AsmToken::RBrac))
3110 return Error(E, "']' expected");
3111 Parser.Lex(); // Eat right bracket token.
3112
3113 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003114 ShiftType, ShiftImm, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00003115 S, E));
3116
Jim Grosbachc320c852011-08-05 21:28:30 +00003117 // If there's a pre-indexing writeback marker, '!', just add it as a token
3118 // operand.
3119 if (Parser.getTok().is(AsmToken::Exclaim)) {
3120 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3121 Parser.Lex(); // Eat the '!'.
3122 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003123
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003124 return false;
3125}
3126
Jim Grosbachd3595712011-08-03 23:50:40 +00003127/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003128/// ( lsl | lsr | asr | ror ) , # shift_amount
3129/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00003130/// return true if it parses a shift otherwise it returns false.
3131bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3132 unsigned &Amount) {
3133 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00003134 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003135 if (Tok.isNot(AsmToken::Identifier))
3136 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00003137 StringRef ShiftName = Tok.getString();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003138 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003139 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003140 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003141 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003142 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003143 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003144 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003145 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003146 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003147 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003148 else
Jim Grosbachd3595712011-08-03 23:50:40 +00003149 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00003150 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003151
Jim Grosbachd3595712011-08-03 23:50:40 +00003152 // rrx stands alone.
3153 Amount = 0;
3154 if (St != ARM_AM::rrx) {
3155 Loc = Parser.getTok().getLoc();
3156 // A '#' and a shift amount.
3157 const AsmToken &HashTok = Parser.getTok();
3158 if (HashTok.isNot(AsmToken::Hash))
3159 return Error(HashTok.getLoc(), "'#' expected");
3160 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003161
Jim Grosbachd3595712011-08-03 23:50:40 +00003162 const MCExpr *Expr;
3163 if (getParser().ParseExpression(Expr))
3164 return true;
3165 // Range check the immediate.
3166 // lsl, ror: 0 <= imm <= 31
3167 // lsr, asr: 0 <= imm <= 32
3168 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3169 if (!CE)
3170 return Error(Loc, "shift amount must be an immediate");
3171 int64_t Imm = CE->getValue();
3172 if (Imm < 0 ||
3173 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3174 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3175 return Error(Loc, "immediate shift value out of range");
3176 Amount = Imm;
3177 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003178
3179 return false;
3180}
3181
Jim Grosbache7fbce72011-10-03 23:38:36 +00003182/// parseFPImm - A floating point immediate expression operand.
3183ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3184parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3185 SMLoc S = Parser.getTok().getLoc();
3186
3187 if (Parser.getTok().isNot(AsmToken::Hash))
3188 return MatchOperand_NoMatch;
3189 Parser.Lex(); // Eat the '#'.
3190
3191 // Handle negation, as that still comes through as a separate token.
3192 bool isNegative = false;
3193 if (Parser.getTok().is(AsmToken::Minus)) {
3194 isNegative = true;
3195 Parser.Lex();
3196 }
3197 const AsmToken &Tok = Parser.getTok();
3198 if (Tok.is(AsmToken::Real)) {
3199 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3200 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3201 // If we had a '-' in front, toggle the sign bit.
3202 IntVal ^= (uint64_t)isNegative << 63;
3203 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3204 Parser.Lex(); // Eat the token.
3205 if (Val == -1) {
3206 TokError("floating point value out of range");
3207 return MatchOperand_ParseFail;
3208 }
3209 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3210 return MatchOperand_Success;
3211 }
3212 if (Tok.is(AsmToken::Integer)) {
3213 int64_t Val = Tok.getIntVal();
3214 Parser.Lex(); // Eat the token.
3215 if (Val > 255 || Val < 0) {
3216 TokError("encoded floating point value out of range");
3217 return MatchOperand_ParseFail;
3218 }
3219 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3220 return MatchOperand_Success;
3221 }
3222
3223 TokError("invalid floating point immediate");
3224 return MatchOperand_ParseFail;
3225}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003226/// Parse a arm instruction operand. For now this parses the operand regardless
3227/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003228bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003229 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003230 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003231
3232 // Check if the current operand has a custom associated parser, if so, try to
3233 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003234 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3235 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003236 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00003237 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3238 // there was a match, but an error occurred, in which case, just return that
3239 // the operand parsing failed.
3240 if (ResTy == MatchOperand_ParseFail)
3241 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003242
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003243 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003244 default:
3245 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00003246 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003247 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003248 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003249 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00003250 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00003251 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00003252 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003253 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003254 else if (Res == -1) // irrecoverable error
3255 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003256 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3257 S = Parser.getTok().getLoc();
3258 Parser.Lex();
3259 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3260 return false;
3261 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003262
3263 // Fall though for the Identifier case that is not a register or a
3264 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00003265 }
Kevin Enderbyb084be92011-01-13 20:32:36 +00003266 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3267 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00003268 // This was not a register so parse other operands that start with an
3269 // identifier (like labels) as expressions and create them as immediates.
3270 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003271 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00003272 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003273 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003274 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003275 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3276 return false;
3277 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003278 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003279 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00003280 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003281 return parseRegisterList(Operands);
Owen Andersonf02d98d2011-08-29 17:17:09 +00003282 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00003283 // #42 -> immediate.
3284 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003285 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003286 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00003287 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00003288 const MCExpr *ImmVal;
3289 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003290 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003291 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3292 if (!CE) {
3293 Error(S, "constant expression expected");
3294 return MatchOperand_ParseFail;
3295 }
3296 int32_t Val = CE->getValue();
3297 if (isNegative && Val == 0)
3298 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003299 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003300 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3301 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003302 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003303 case AsmToken::Colon: {
3304 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00003305 // FIXME: Check it's an expression prefix,
3306 // e.g. (FOO - :lower16:BAR) isn't legal.
3307 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003308 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003309 return true;
3310
Evan Cheng965b3c72011-01-13 07:58:56 +00003311 const MCExpr *SubExprVal;
3312 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003313 return true;
3314
Evan Cheng965b3c72011-01-13 07:58:56 +00003315 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3316 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00003317 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00003318 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00003319 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003320 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003321 }
3322}
3323
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003324// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00003325// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003326bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00003327 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003328
3329 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00003330 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00003331 Parser.Lex(); // Eat ':'
3332
3333 if (getLexer().isNot(AsmToken::Identifier)) {
3334 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3335 return true;
3336 }
3337
3338 StringRef IDVal = Parser.getTok().getIdentifier();
3339 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003340 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003341 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003342 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003343 } else {
3344 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3345 return true;
3346 }
3347 Parser.Lex();
3348
3349 if (getLexer().isNot(AsmToken::Colon)) {
3350 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3351 return true;
3352 }
3353 Parser.Lex(); // Eat the last ':'
3354 return false;
3355}
3356
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003357/// \brief Given a mnemonic, split out possible predication code and carry
3358/// setting letters to form a canonical mnemonic and flags.
3359//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003360// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003361// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003362StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003363 unsigned &PredicationCode,
3364 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003365 unsigned &ProcessorIMod,
3366 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003367 PredicationCode = ARMCC::AL;
3368 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003369 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003370
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003371 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003372 //
3373 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003374 if ((Mnemonic == "movs" && isThumb()) ||
3375 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3376 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3377 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3378 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3379 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3380 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3381 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003382 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003383
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003384 // First, split out any predication code. Ignore mnemonics we know aren't
3385 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00003386 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00003387 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00003388 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00003389 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003390 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3391 .Case("eq", ARMCC::EQ)
3392 .Case("ne", ARMCC::NE)
3393 .Case("hs", ARMCC::HS)
3394 .Case("cs", ARMCC::HS)
3395 .Case("lo", ARMCC::LO)
3396 .Case("cc", ARMCC::LO)
3397 .Case("mi", ARMCC::MI)
3398 .Case("pl", ARMCC::PL)
3399 .Case("vs", ARMCC::VS)
3400 .Case("vc", ARMCC::VC)
3401 .Case("hi", ARMCC::HI)
3402 .Case("ls", ARMCC::LS)
3403 .Case("ge", ARMCC::GE)
3404 .Case("lt", ARMCC::LT)
3405 .Case("gt", ARMCC::GT)
3406 .Case("le", ARMCC::LE)
3407 .Case("al", ARMCC::AL)
3408 .Default(~0U);
3409 if (CC != ~0U) {
3410 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3411 PredicationCode = CC;
3412 }
Bill Wendling193961b2010-10-29 23:50:21 +00003413 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003414
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003415 // Next, determine if we have a carry setting bit. We explicitly ignore all
3416 // the instructions we know end in 's'.
3417 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00003418 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003419 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3420 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3421 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00003422 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3423 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003424 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3425 CarrySetting = true;
3426 }
3427
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003428 // The "cps" instruction can have a interrupt mode operand which is glued into
3429 // the mnemonic. Check if this is the case, split it and parse the imod op
3430 if (Mnemonic.startswith("cps")) {
3431 // Split out any imod code.
3432 unsigned IMod =
3433 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3434 .Case("ie", ARM_PROC::IE)
3435 .Case("id", ARM_PROC::ID)
3436 .Default(~0U);
3437 if (IMod != ~0U) {
3438 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3439 ProcessorIMod = IMod;
3440 }
3441 }
3442
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003443 // The "it" instruction has the condition mask on the end of the mnemonic.
3444 if (Mnemonic.startswith("it")) {
3445 ITMask = Mnemonic.slice(2, Mnemonic.size());
3446 Mnemonic = Mnemonic.slice(0, 2);
3447 }
3448
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003449 return Mnemonic;
3450}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003451
3452/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3453/// inclusion of carry set or predication code operands.
3454//
3455// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003456void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003457getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003458 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00003459 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3460 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003461 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003462 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003463 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003464 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003465 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003466 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003467 Mnemonic == "mla" || Mnemonic == "smlal" ||
3468 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00003469 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003470 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00003471 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003472
Daniel Dunbar09264122011-01-11 19:06:29 +00003473 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3474 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3475 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3476 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00003477 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3478 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00003479 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00003480 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw") &&
3481 !isThumb()) ||
3482 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3483 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00003484 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003485 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003486 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003487 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003488
Jim Grosbach6c45b752011-09-16 16:39:25 +00003489 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003490 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00003491 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003492 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003493 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003494}
3495
Jim Grosbach7283da92011-08-16 21:12:37 +00003496bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3497 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003498 // FIXME: This is all horribly hacky. We really need a better way to deal
3499 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00003500
3501 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3502 // another does not. Specifically, the MOVW instruction does not. So we
3503 // special case it here and remove the defaulted (non-setting) cc_out
3504 // operand if that's the instruction we're trying to match.
3505 //
3506 // We do this as post-processing of the explicit operands rather than just
3507 // conditionally adding the cc_out in the first place because we need
3508 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00003509 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00003510 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3511 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3512 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3513 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00003514
3515 // Register-register 'add' for thumb does not have a cc_out operand
3516 // when there are only two register operands.
3517 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3518 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3519 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3520 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3521 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003522 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003523 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3524 // have to check the immediate range here since Thumb2 has a variant
3525 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003526 if (((isThumb() && Mnemonic == "add") ||
3527 (isThumbTwo() && Mnemonic == "sub")) &&
3528 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003529 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3530 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3531 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003532 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3533 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3534 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003535 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003536 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3537 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003538 // selecting via the generic "add" mnemonic, so to know that we
3539 // should remove the cc_out operand, we have to explicitly check that
3540 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003541 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3542 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003543 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3544 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3545 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3546 // Nest conditions rather than one big 'if' statement for readability.
3547 //
3548 // If either register is a high reg, it's either one of the SP
3549 // variants (handled above) or a 32-bit encoding, so we just
3550 // check against T3.
3551 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3552 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3553 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3554 return false;
3555 // If both registers are low, we're in an IT block, and the immediate is
3556 // in range, we should use encoding T1 instead, which has a cc_out.
3557 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00003558 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003559 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3560 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3561 return false;
3562
3563 // Otherwise, we use encoding T4, which does not have a cc_out
3564 // operand.
3565 return true;
3566 }
3567
Jim Grosbach9c8b9932011-09-14 21:00:40 +00003568 // The thumb2 multiply instruction doesn't have a CCOut register, so
3569 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3570 // use the 16-bit encoding or not.
3571 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3572 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3573 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3574 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3575 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3576 // If the registers aren't low regs, the destination reg isn't the
3577 // same as one of the source regs, or the cc_out operand is zero
3578 // outside of an IT block, we have to use the 32-bit encoding, so
3579 // remove the cc_out operand.
3580 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3581 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3582 !inITBlock() ||
3583 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3584 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3585 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3586 static_cast<ARMOperand*>(Operands[4])->getReg())))
3587 return true;
3588
3589
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003590
Jim Grosbach4b701af2011-08-24 21:42:27 +00003591 // Register-register 'add/sub' for thumb does not have a cc_out operand
3592 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3593 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3594 // right, this will result in better diagnostics (which operand is off)
3595 // anyway.
3596 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3597 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003598 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3599 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3600 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3601 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00003602
Jim Grosbach7283da92011-08-16 21:12:37 +00003603 return false;
3604}
3605
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003606/// Parse an arm instruction mnemonic followed by its operands.
3607bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3608 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3609 // Create the leading tokens for the mnemonic, split by '.' characters.
3610 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003611 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003612
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003613 // Split out the predication code and carry setting flag from the mnemonic.
3614 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003615 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003616 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003617 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003618 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003619 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003620
Jim Grosbach1c171b12011-08-25 17:23:55 +00003621 // In Thumb1, only the branch (B) instruction can be predicated.
3622 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3623 Parser.EatToEndOfStatement();
3624 return Error(NameLoc, "conditional execution not supported in Thumb1");
3625 }
3626
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003627 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3628
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003629 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3630 // is the mask as it will be for the IT encoding if the conditional
3631 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3632 // where the conditional bit0 is zero, the instruction post-processing
3633 // will adjust the mask accordingly.
3634 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00003635 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3636 if (ITMask.size() > 3) {
3637 Parser.EatToEndOfStatement();
3638 return Error(Loc, "too many conditions on IT instruction");
3639 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003640 unsigned Mask = 8;
3641 for (unsigned i = ITMask.size(); i != 0; --i) {
3642 char pos = ITMask[i - 1];
3643 if (pos != 't' && pos != 'e') {
3644 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00003645 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003646 }
3647 Mask >>= 1;
3648 if (ITMask[i - 1] == 't')
3649 Mask |= 8;
3650 }
Jim Grosbached16ec42011-08-29 22:24:09 +00003651 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003652 }
3653
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003654 // FIXME: This is all a pretty gross hack. We should automatically handle
3655 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00003656
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003657 // Next, add the CCOut and ConditionCode operands, if needed.
3658 //
3659 // For mnemonics which can ever incorporate a carry setting bit or predication
3660 // code, our matching model involves us always generating CCOut and
3661 // ConditionCode operands to match the mnemonic "as written" and then we let
3662 // the matcher deal with finding the right instruction or generating an
3663 // appropriate error.
3664 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003665 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003666
Jim Grosbach03a8a162011-07-14 22:04:21 +00003667 // If we had a carry-set on an instruction that can't do that, issue an
3668 // error.
3669 if (!CanAcceptCarrySet && CarrySetting) {
3670 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003671 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00003672 "' can not set flags, but 's' suffix specified");
3673 }
Jim Grosbach0a547702011-07-22 17:44:50 +00003674 // If we had a predication code on an instruction that can't do that, issue an
3675 // error.
3676 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3677 Parser.EatToEndOfStatement();
3678 return Error(NameLoc, "instruction '" + Mnemonic +
3679 "' is not predicable, but condition code specified");
3680 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00003681
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003682 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00003683 if (CanAcceptCarrySet) {
3684 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003685 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00003686 Loc));
3687 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003688
3689 // Add the predication code operand, if necessary.
3690 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00003691 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3692 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003693 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00003694 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003695 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003696
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003697 // Add the processor imod operand, if necessary.
3698 if (ProcessorIMod) {
3699 Operands.push_back(ARMOperand::CreateImm(
3700 MCConstantExpr::Create(ProcessorIMod, getContext()),
3701 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003702 }
3703
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003704 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003705 while (Next != StringRef::npos) {
3706 Start = Next;
3707 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003708 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003709
Jim Grosbach838ed3a2011-08-24 22:19:48 +00003710 // For now, we're only parsing Thumb1 (for the most part), so
3711 // just ignore ".n" qualifiers. We'll use them to restrict
3712 // matching when we do Thumb2.
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00003713 if (ExtraToken != ".n") {
3714 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3715 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3716 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003717 }
3718
3719 // Read the remaining operands.
3720 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003721 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003722 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00003723 Parser.EatToEndOfStatement();
3724 return true;
3725 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003726
3727 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00003728 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003729
3730 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003731 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00003732 Parser.EatToEndOfStatement();
3733 return true;
3734 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003735 }
3736 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00003737
Chris Lattnera2a9d162010-09-11 16:18:25 +00003738 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00003739 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00003740 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00003741 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00003742 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003743
Chris Lattner91689c12010-09-08 05:10:46 +00003744 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003745
Jim Grosbach7283da92011-08-16 21:12:37 +00003746 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3747 // do and don't have a cc_out optional-def operand. With some spot-checks
3748 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003749 // parse and adjust accordingly before actually matching. We shouldn't ever
3750 // try to remove a cc_out operand that was explicitly set on the the
3751 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3752 // table driven matcher doesn't fit well with the ARM instruction set.
3753 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003754 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3755 Operands.erase(Operands.begin() + 1);
3756 delete Op;
3757 }
3758
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00003759 // ARM mode 'blx' need special handling, as the register operand version
3760 // is predicable, but the label operand version is not. So, we can't rely
3761 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00003762 // a k_CondCode operand in the list. If we're trying to match the label
3763 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00003764 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3765 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3766 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3767 Operands.erase(Operands.begin() + 1);
3768 delete Op;
3769 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00003770
3771 // The vector-compare-to-zero instructions have a literal token "#0" at
3772 // the end that comes to here as an immediate operand. Convert it to a
3773 // token to play nicely with the matcher.
3774 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3775 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3776 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3777 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3778 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3779 if (CE && CE->getValue() == 0) {
3780 Operands.erase(Operands.begin() + 5);
3781 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3782 delete Op;
3783 }
3784 }
Jim Grosbach46b66462011-10-03 22:30:24 +00003785 // VCMP{E} does the same thing, but with a different operand count.
3786 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3787 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3788 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3789 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3790 if (CE && CE->getValue() == 0) {
3791 Operands.erase(Operands.begin() + 4);
3792 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3793 delete Op;
3794 }
3795 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00003796 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
3797 // end. Convert it to a token here.
3798 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
3799 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3800 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3801 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3802 if (CE && CE->getValue() == 0) {
3803 Operands.erase(Operands.begin() + 5);
3804 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3805 delete Op;
3806 }
3807 }
3808
Chris Lattnerf29c0b62010-01-14 22:21:20 +00003809 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00003810}
3811
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003812// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00003813
3814// return 'true' if register list contains non-low GPR registers,
3815// 'false' otherwise. If Reg is in the register list or is HiReg, set
3816// 'containsReg' to true.
3817static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
3818 unsigned HiReg, bool &containsReg) {
3819 containsReg = false;
3820 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3821 unsigned OpReg = Inst.getOperand(i).getReg();
3822 if (OpReg == Reg)
3823 containsReg = true;
3824 // Anything other than a low register isn't legal here.
3825 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
3826 return true;
3827 }
3828 return false;
3829}
3830
Jim Grosbacha31f2232011-09-07 18:05:34 +00003831// Check if the specified regisgter is in the register list of the inst,
3832// starting at the indicated operand number.
3833static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
3834 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3835 unsigned OpReg = Inst.getOperand(i).getReg();
3836 if (OpReg == Reg)
3837 return true;
3838 }
3839 return false;
3840}
3841
Jim Grosbached16ec42011-08-29 22:24:09 +00003842// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
3843// the ARMInsts array) instead. Getting that here requires awkward
3844// API changes, though. Better way?
3845namespace llvm {
3846extern MCInstrDesc ARMInsts[];
3847}
3848static MCInstrDesc &getInstDesc(unsigned Opcode) {
3849 return ARMInsts[Opcode];
3850}
3851
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003852// FIXME: We would really like to be able to tablegen'erate this.
3853bool ARMAsmParser::
3854validateInstruction(MCInst &Inst,
3855 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbached16ec42011-08-29 22:24:09 +00003856 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3857 SMLoc Loc = Operands[0]->getStartLoc();
3858 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00003859 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
3860 // being allowed in IT blocks, but not being predicable. It just always
3861 // executes.
3862 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00003863 unsigned bit = 1;
3864 if (ITState.FirstCond)
3865 ITState.FirstCond = false;
3866 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00003867 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00003868 // The instruction must be predicable.
3869 if (!MCID.isPredicable())
3870 return Error(Loc, "instructions in IT block must be predicable");
3871 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
3872 unsigned ITCond = bit ? ITState.Cond :
3873 ARMCC::getOppositeCondition(ITState.Cond);
3874 if (Cond != ITCond) {
3875 // Find the condition code Operand to get its SMLoc information.
3876 SMLoc CondLoc;
3877 for (unsigned i = 1; i < Operands.size(); ++i)
3878 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
3879 CondLoc = Operands[i]->getStartLoc();
3880 return Error(CondLoc, "incorrect condition in IT block; got '" +
3881 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
3882 "', but expected '" +
3883 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
3884 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00003885 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00003886 } else if (isThumbTwo() && MCID.isPredicable() &&
3887 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00003888 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
3889 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00003890 return Error(Loc, "predicated instructions must be in IT block");
3891
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003892 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00003893 case ARM::LDRD:
3894 case ARM::LDRD_PRE:
3895 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003896 case ARM::LDREXD: {
3897 // Rt2 must be Rt + 1.
3898 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3899 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3900 if (Rt2 != Rt + 1)
3901 return Error(Operands[3]->getStartLoc(),
3902 "destination operands must be sequential");
3903 return false;
3904 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00003905 case ARM::STRD: {
3906 // Rt2 must be Rt + 1.
3907 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3908 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3909 if (Rt2 != Rt + 1)
3910 return Error(Operands[3]->getStartLoc(),
3911 "source operands must be sequential");
3912 return false;
3913 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00003914 case ARM::STRD_PRE:
3915 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003916 case ARM::STREXD: {
3917 // Rt2 must be Rt + 1.
3918 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3919 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
3920 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00003921 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003922 "source operands must be sequential");
3923 return false;
3924 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00003925 case ARM::SBFX:
3926 case ARM::UBFX: {
3927 // width must be in range [1, 32-lsb]
3928 unsigned lsb = Inst.getOperand(2).getImm();
3929 unsigned widthm1 = Inst.getOperand(3).getImm();
3930 if (widthm1 >= 32 - lsb)
3931 return Error(Operands[5]->getStartLoc(),
3932 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00003933 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00003934 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00003935 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00003936 // If we're parsing Thumb2, the .w variant is available and handles
3937 // most cases that are normally illegal for a Thumb1 LDM
3938 // instruction. We'll make the transformation in processInstruction()
3939 // if necessary.
3940 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00003941 // Thumb LDM instructions are writeback iff the base register is not
3942 // in the register list.
3943 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00003944 bool hasWritebackToken =
3945 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
3946 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00003947 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00003948 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00003949 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
3950 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00003951 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00003952 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00003953 return Error(Operands[2]->getStartLoc(),
3954 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00003955 // If we should not have writeback, there must not be a '!'. This is
3956 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00003957 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00003958 return Error(Operands[3]->getStartLoc(),
3959 "writeback operator '!' not allowed when base register "
3960 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00003961
3962 break;
3963 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00003964 case ARM::t2LDMIA_UPD: {
3965 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
3966 return Error(Operands[4]->getStartLoc(),
3967 "writeback operator '!' not allowed when base register "
3968 "in register list");
3969 break;
3970 }
Jim Grosbach38c59fc2011-08-22 23:17:34 +00003971 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00003972 bool listContainsBase;
3973 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
3974 return Error(Operands[2]->getStartLoc(),
3975 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00003976 break;
3977 }
3978 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00003979 bool listContainsBase;
3980 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
3981 return Error(Operands[2]->getStartLoc(),
3982 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00003983 break;
3984 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00003985 case ARM::tSTMIA_UPD: {
3986 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00003987 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00003988 return Error(Operands[4]->getStartLoc(),
3989 "registers must be in range r0-r7");
3990 break;
3991 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003992 }
3993
3994 return false;
3995}
3996
Jim Grosbach8ba76c62011-08-11 17:35:48 +00003997void ARMAsmParser::
3998processInstruction(MCInst &Inst,
3999 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4000 switch (Inst.getOpcode()) {
4001 case ARM::LDMIA_UPD:
4002 // If this is a load of a single register via a 'pop', then we should use
4003 // a post-indexed LDR instruction instead, per the ARM ARM.
4004 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4005 Inst.getNumOperands() == 5) {
4006 MCInst TmpInst;
4007 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4008 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4009 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4010 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4011 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4012 TmpInst.addOperand(MCOperand::CreateImm(4));
4013 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4014 TmpInst.addOperand(Inst.getOperand(3));
4015 Inst = TmpInst;
4016 }
4017 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00004018 case ARM::STMDB_UPD:
4019 // If this is a store of a single register via a 'push', then we should use
4020 // a pre-indexed STR instruction instead, per the ARM ARM.
4021 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4022 Inst.getNumOperands() == 5) {
4023 MCInst TmpInst;
4024 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4025 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4026 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4027 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4028 TmpInst.addOperand(MCOperand::CreateImm(-4));
4029 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4030 TmpInst.addOperand(Inst.getOperand(3));
4031 Inst = TmpInst;
4032 }
4033 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004034 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00004035 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4036 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4037 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4038 // to encoding T1 if <Rd> is omitted."
4039 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004040 Inst.setOpcode(ARM::tADDi3);
4041 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004042 case ARM::tSUBi8:
4043 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4044 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4045 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4046 // to encoding T1 if <Rd> is omitted."
4047 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4048 Inst.setOpcode(ARM::tSUBi3);
4049 break;
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004050 case ARM::tB:
4051 // A Thumb conditional branch outside of an IT block is a tBcc.
4052 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4053 Inst.setOpcode(ARM::tBcc);
4054 break;
4055 case ARM::t2B:
4056 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4057 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4058 Inst.setOpcode(ARM::t2Bcc);
4059 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00004060 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004061 // If the conditional is AL or we're in an IT block, we really want t2B.
4062 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbach99bc8462011-08-31 21:17:31 +00004063 Inst.setOpcode(ARM::t2B);
4064 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00004065 case ARM::tBcc:
4066 // If the conditional is AL, we really want tB.
4067 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4068 Inst.setOpcode(ARM::tB);
Jim Grosbach6ddb5682011-08-18 16:08:39 +00004069 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004070 case ARM::tLDMIA: {
4071 // If the register list contains any high registers, or if the writeback
4072 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4073 // instead if we're in Thumb2. Otherwise, this should have generated
4074 // an error in validateInstruction().
4075 unsigned Rn = Inst.getOperand(0).getReg();
4076 bool hasWritebackToken =
4077 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4078 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4079 bool listContainsBase;
4080 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4081 (!listContainsBase && !hasWritebackToken) ||
4082 (listContainsBase && hasWritebackToken)) {
4083 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4084 assert (isThumbTwo());
4085 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4086 // If we're switching to the updating version, we need to insert
4087 // the writeback tied operand.
4088 if (hasWritebackToken)
4089 Inst.insert(Inst.begin(),
4090 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4091 }
4092 break;
4093 }
Jim Grosbach099c9762011-09-16 20:50:13 +00004094 case ARM::tSTMIA_UPD: {
4095 // If the register list contains any high registers, we need to use
4096 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4097 // should have generated an error in validateInstruction().
4098 unsigned Rn = Inst.getOperand(0).getReg();
4099 bool listContainsBase;
4100 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4101 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4102 assert (isThumbTwo());
4103 Inst.setOpcode(ARM::t2STMIA_UPD);
4104 }
4105 break;
4106 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004107 case ARM::t2MOVi: {
4108 // If we can use the 16-bit encoding and the user didn't explicitly
4109 // request the 32-bit variant, transform it here.
4110 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4111 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00004112 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4113 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4114 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004115 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4116 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4117 // The operands aren't in the same order for tMOVi8...
4118 MCInst TmpInst;
4119 TmpInst.setOpcode(ARM::tMOVi8);
4120 TmpInst.addOperand(Inst.getOperand(0));
4121 TmpInst.addOperand(Inst.getOperand(4));
4122 TmpInst.addOperand(Inst.getOperand(1));
4123 TmpInst.addOperand(Inst.getOperand(2));
4124 TmpInst.addOperand(Inst.getOperand(3));
4125 Inst = TmpInst;
4126 }
4127 break;
4128 }
4129 case ARM::t2MOVr: {
4130 // If we can use the 16-bit encoding and the user didn't explicitly
4131 // request the 32-bit variant, transform it here.
4132 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4133 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4134 Inst.getOperand(2).getImm() == ARMCC::AL &&
4135 Inst.getOperand(4).getReg() == ARM::CPSR &&
4136 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4137 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4138 // The operands aren't the same for tMOV[S]r... (no cc_out)
4139 MCInst TmpInst;
4140 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4141 TmpInst.addOperand(Inst.getOperand(0));
4142 TmpInst.addOperand(Inst.getOperand(1));
4143 TmpInst.addOperand(Inst.getOperand(2));
4144 TmpInst.addOperand(Inst.getOperand(3));
4145 Inst = TmpInst;
4146 }
4147 break;
4148 }
Jim Grosbach82213192011-09-19 20:29:33 +00004149 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00004150 case ARM::t2SXTB:
4151 case ARM::t2UXTH:
4152 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00004153 // If we can use the 16-bit encoding and the user didn't explicitly
4154 // request the 32-bit variant, transform it here.
4155 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4156 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4157 Inst.getOperand(2).getImm() == 0 &&
4158 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4159 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00004160 unsigned NewOpc;
4161 switch (Inst.getOpcode()) {
4162 default: llvm_unreachable("Illegal opcode!");
4163 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4164 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4165 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4166 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4167 }
Jim Grosbach82213192011-09-19 20:29:33 +00004168 // The operands aren't the same for thumb1 (no rotate operand).
4169 MCInst TmpInst;
4170 TmpInst.setOpcode(NewOpc);
4171 TmpInst.addOperand(Inst.getOperand(0));
4172 TmpInst.addOperand(Inst.getOperand(1));
4173 TmpInst.addOperand(Inst.getOperand(3));
4174 TmpInst.addOperand(Inst.getOperand(4));
4175 Inst = TmpInst;
4176 }
4177 break;
4178 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004179 case ARM::t2IT: {
4180 // The mask bits for all but the first condition are represented as
4181 // the low bit of the condition code value implies 't'. We currently
4182 // always have 1 implies 't', so XOR toggle the bits if the low bit
4183 // of the condition code is zero. The encoding also expects the low
4184 // bit of the condition to be encoded as bit 4 of the mask operand,
4185 // so mask that in if needed
4186 MCOperand &MO = Inst.getOperand(1);
4187 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00004188 unsigned OrigMask = Mask;
4189 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004190 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004191 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4192 for (unsigned i = 3; i != TZ; --i)
4193 Mask ^= 1 << i;
4194 } else
4195 Mask |= 0x10;
4196 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00004197
4198 // Set up the IT block state according to the IT instruction we just
4199 // matched.
4200 assert(!inITBlock() && "nested IT blocks?!");
4201 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4202 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4203 ITState.CurPosition = 0;
4204 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004205 break;
4206 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004207 }
4208}
4209
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004210unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4211 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4212 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004213 unsigned Opc = Inst.getOpcode();
4214 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004215 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4216 assert(MCID.hasOptionalDef() &&
4217 "optionally flag setting instruction missing optional def operand");
4218 assert(MCID.NumOperands == Inst.getNumOperands() &&
4219 "operand count mismatch!");
4220 // Find the optional-def operand (cc_out).
4221 unsigned OpNo;
4222 for (OpNo = 0;
4223 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4224 ++OpNo)
4225 ;
4226 // If we're parsing Thumb1, reject it completely.
4227 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4228 return Match_MnemonicFail;
4229 // If we're parsing Thumb2, which form is legal depends on whether we're
4230 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004231 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4232 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004233 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00004234 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4235 inITBlock())
4236 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004237 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004238 // Some high-register supporting Thumb1 encodings only allow both registers
4239 // to be from r0-r7 when in Thumb2.
4240 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4241 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4242 isARMLowRegister(Inst.getOperand(2).getReg()))
4243 return Match_RequiresThumb2;
4244 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00004245 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004246 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4247 isARMLowRegister(Inst.getOperand(1).getReg()))
4248 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004249 return Match_Success;
4250}
4251
Chris Lattner9487de62010-10-28 21:28:01 +00004252bool ARMAsmParser::
4253MatchAndEmitInstruction(SMLoc IDLoc,
4254 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4255 MCStreamer &Out) {
4256 MCInst Inst;
4257 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00004258 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00004259 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00004260 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00004261 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004262 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004263 // Context sensitive operand constraints aren't handled by the matcher,
4264 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004265 if (validateInstruction(Inst, Operands)) {
4266 // Still progress the IT block, otherwise one wrong condition causes
4267 // nasty cascading errors.
4268 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004269 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004270 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004271
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004272 // Some instructions need post-processing to, for example, tweak which
4273 // encoding is selected.
4274 processInstruction(Inst, Operands);
4275
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004276 // Only move forward at the very end so that everything in validate
4277 // and process gets a consistent answer about whether we're in an IT
4278 // block.
4279 forwardITPosition();
4280
Chris Lattner9487de62010-10-28 21:28:01 +00004281 Out.EmitInstruction(Inst);
4282 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004283 case Match_MissingFeature:
4284 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4285 return true;
4286 case Match_InvalidOperand: {
4287 SMLoc ErrorLoc = IDLoc;
4288 if (ErrorInfo != ~0U) {
4289 if (ErrorInfo >= Operands.size())
4290 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00004291
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004292 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4293 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4294 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004295
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004296 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00004297 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004298 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004299 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00004300 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00004301 // The converter function will have already emited a diagnostic.
4302 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00004303 case Match_RequiresNotITBlock:
4304 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004305 case Match_RequiresITBlock:
4306 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004307 case Match_RequiresV6:
4308 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4309 case Match_RequiresThumb2:
4310 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004311 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004312
Eric Christopher91d7b902010-10-29 09:26:59 +00004313 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004314 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00004315}
4316
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004317/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00004318bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4319 StringRef IDVal = DirectiveID.getIdentifier();
4320 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004321 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004322 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004323 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004324 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004325 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004326 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004327 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004328 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004329 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00004330 return true;
4331}
4332
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004333/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00004334/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004335bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00004336 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4337 for (;;) {
4338 const MCExpr *Value;
4339 if (getParser().ParseExpression(Value))
4340 return true;
4341
Chris Lattnerc35681b2010-01-19 19:46:13 +00004342 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00004343
4344 if (getLexer().is(AsmToken::EndOfStatement))
4345 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00004346
Kevin Enderbyccab3172009-09-15 00:27:25 +00004347 // FIXME: Improve diagnostic.
4348 if (getLexer().isNot(AsmToken::Comma))
4349 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004350 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004351 }
4352 }
4353
Sean Callanana83fd7d2010-01-19 20:27:46 +00004354 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004355 return false;
4356}
4357
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004358/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00004359/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004360bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00004361 if (getLexer().isNot(AsmToken::EndOfStatement))
4362 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004363 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004364
4365 // TODO: set thumb mode
4366 // TODO: tell the MC streamer the mode
4367 // getParser().getStreamer().Emit???();
4368 return false;
4369}
4370
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004371/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00004372/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004373bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004374 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4375 bool isMachO = MAI.hasSubsectionsViaSymbols();
4376 StringRef Name;
4377
4378 // Darwin asm has function name after .thumb_func direction
4379 // ELF doesn't
4380 if (isMachO) {
4381 const AsmToken &Tok = Parser.getTok();
4382 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4383 return Error(L, "unexpected token in .thumb_func directive");
4384 Name = Tok.getString();
4385 Parser.Lex(); // Consume the identifier token.
4386 }
4387
Kevin Enderby146dcf22009-10-15 20:48:48 +00004388 if (getLexer().isNot(AsmToken::EndOfStatement))
4389 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004390 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004391
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004392 // FIXME: assuming function name will be the line following .thumb_func
4393 if (!isMachO) {
4394 Name = Parser.getTok().getString();
4395 }
4396
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00004397 // Mark symbol as a thumb symbol.
4398 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4399 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004400 return false;
4401}
4402
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004403/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00004404/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004405bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004406 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004407 if (Tok.isNot(AsmToken::Identifier))
4408 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00004409 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00004410 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00004411 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004412 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00004413 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00004414 else
4415 return Error(L, "unrecognized syntax mode in .syntax directive");
4416
4417 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004418 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004419 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004420
4421 // TODO tell the MC streamer the mode
4422 // getParser().getStreamer().Emit???();
4423 return false;
4424}
4425
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004426/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00004427/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004428bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004429 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004430 if (Tok.isNot(AsmToken::Integer))
4431 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00004432 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00004433 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004434 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004435 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004436 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004437 else
4438 return Error(L, "invalid operand to .code directive");
4439
4440 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004441 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004442 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004443
Evan Cheng284b4672011-07-08 22:36:29 +00004444 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004445 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004446 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004447 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00004448 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004449 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004450 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004451 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00004452 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00004453
Kevin Enderby146dcf22009-10-15 20:48:48 +00004454 return false;
4455}
4456
Sean Callanan643a5572010-04-07 20:29:34 +00004457extern "C" void LLVMInitializeARMAsmLexer();
4458
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004459/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00004460extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00004461 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4462 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00004463 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004464}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00004465
Chris Lattner3e4582a2010-09-06 19:11:01 +00004466#define GET_REGISTER_MATCHER
4467#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00004468#include "ARMGenAsmMatcher.inc"