blob: 8803b6877824b9b9106e95febb8c7db07e0e7ae2 [file] [log] [blame]
Kevin Enderbyca9c42c2009-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 Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-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 Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Owen Anderson0c9f2502011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000036
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattner3a697562010-10-28 17:20:03 +000039namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000042
Evan Cheng94b95502011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbachf8e1e3e2011-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 Grosbacha1109882011-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 Grosbachf8e1e3e2011-08-29 22:24:09 +000075
76
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-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 Enderbyca9c42c2009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbach1355cf12011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-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 Enderby515d5092009-10-15 20:48:48 +000097
Jim Grosbach1355cf12011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000103
Evan Chengebdeeab2011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloyacad68d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng32869202011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000123 }
James Molloyacad68d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000127
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000130
Chris Lattner0692ee62010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach89df9962011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000141 OperandMatchResultTy parseCoprocOptionOperand(
142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000143 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000149 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
150 StringRef Op, int Low, int High);
151 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
152 return parsePKHImm(O, "lsl", 0, 31);
153 }
154 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
155 return parsePKHImm(O, "asr", 1, 32);
156 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000157 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000158 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000159 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000160 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000161 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000162 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000163 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000164 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000165
166 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000167 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
168 const SmallVectorImpl<MCParsedAsmOperand*> &);
169 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
170 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000171 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
172 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000173 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
174 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000175 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000176 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000177 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000179 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000181 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000183 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000185 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
187 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
189 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
191 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000193 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000195 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000197 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000199 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000201 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
203 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000205
206 bool validateInstruction(MCInst &Inst,
207 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000208 void processInstruction(MCInst &Inst,
209 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000210 bool shouldOmitCCOutOperand(StringRef Mnemonic,
211 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000212
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000213public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000214 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000215 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000216 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000217 Match_RequiresV6,
218 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000219 };
220
Evan Chengffc0e732011-07-09 05:47:46 +0000221 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000222 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000223 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000224
Evan Chengebdeeab2011-07-08 01:53:10 +0000225 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000226 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000227
228 // Not in an ITBlock to start with.
229 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000230 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000231
Jim Grosbach1355cf12011-07-26 17:10:22 +0000232 // Implementation of the MCTargetAsmParser interface:
233 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
234 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000235 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000236 bool ParseDirective(AsmToken DirectiveID);
237
Jim Grosbach47a0d522011-08-16 20:45:50 +0000238 unsigned checkTargetMatchPredicate(MCInst &Inst);
239
Jim Grosbach1355cf12011-07-26 17:10:22 +0000240 bool MatchAndEmitInstruction(SMLoc IDLoc,
241 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
242 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000243};
Jim Grosbach16c74252010-10-29 14:46:02 +0000244} // end anonymous namespace
245
Chris Lattner3a697562010-10-28 17:20:03 +0000246namespace {
247
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000248/// ARMOperand - Instances of this class represent a parsed ARM machine
249/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000250class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000251 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000252 k_CondCode,
253 k_CCOut,
254 k_ITCondMask,
255 k_CoprocNum,
256 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000257 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000258 k_Immediate,
259 k_FPImmediate,
260 k_MemBarrierOpt,
261 k_Memory,
262 k_PostIndexRegister,
263 k_MSRMask,
264 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000265 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_Register,
267 k_RegisterList,
268 k_DPRRegisterList,
269 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000270 k_VectorList,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000271 k_ShiftedRegister,
272 k_ShiftedImmediate,
273 k_ShifterImmediate,
274 k_RotateImmediate,
275 k_BitfieldDescriptor,
276 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000277 } Kind;
278
Sean Callanan76264762010-04-02 22:27:05 +0000279 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000280 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000281
282 union {
283 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000284 ARMCC::CondCodes Val;
285 } CC;
286
287 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000288 unsigned Val;
289 } Cop;
290
291 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000292 unsigned Val;
293 } CoprocOption;
294
295 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000296 unsigned Mask:4;
297 } ITMask;
298
299 struct {
300 ARM_MB::MemBOpt Val;
301 } MBOpt;
302
303 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000304 ARM_PROC::IFlags Val;
305 } IFlags;
306
307 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000308 unsigned Val;
309 } MMask;
310
311 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000312 const char *Data;
313 unsigned Length;
314 } Tok;
315
316 struct {
317 unsigned RegNum;
318 } Reg;
319
Jim Grosbach862019c2011-10-18 23:02:30 +0000320 // A vector register list is a sequential list of 1 to 4 registers.
321 struct {
322 unsigned RegNum;
323 unsigned Count;
324 } VectorList;
325
Bill Wendling8155e5b2010-11-06 22:19:43 +0000326 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000327 unsigned Val;
328 } VectorIndex;
329
330 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000331 const MCExpr *Val;
332 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000333
Jim Grosbach9d390362011-10-03 23:38:36 +0000334 struct {
335 unsigned Val; // encoded 8-bit representation
336 } FPImm;
337
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000338 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000339 struct {
340 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000341 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
342 // was specified.
343 const MCConstantExpr *OffsetImm; // Offset immediate value
344 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
345 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000346 unsigned ShiftImm; // shift for OffsetReg.
347 unsigned Alignment; // 0 = no alignment specified
348 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000349 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000350 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000351
352 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000353 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000354 bool isAdd;
355 ARM_AM::ShiftOpc ShiftTy;
356 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000357 } PostIdxReg;
358
359 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000360 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000361 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000362 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000363 struct {
364 ARM_AM::ShiftOpc ShiftTy;
365 unsigned SrcReg;
366 unsigned ShiftReg;
367 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000368 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000369 struct {
370 ARM_AM::ShiftOpc ShiftTy;
371 unsigned SrcReg;
372 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000373 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000374 struct {
375 unsigned Imm;
376 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000377 struct {
378 unsigned LSB;
379 unsigned Width;
380 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000381 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000382
Bill Wendling146018f2010-11-06 21:42:12 +0000383 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
384public:
Sean Callanan76264762010-04-02 22:27:05 +0000385 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
386 Kind = o.Kind;
387 StartLoc = o.StartLoc;
388 EndLoc = o.EndLoc;
389 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000390 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000391 CC = o.CC;
392 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000393 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000394 ITMask = o.ITMask;
395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000397 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000398 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_CCOut:
400 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000401 Reg = o.Reg;
402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_RegisterList:
404 case k_DPRRegisterList:
405 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000406 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000407 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000408 case k_VectorList:
409 VectorList = o.VectorList;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_CoprocNum:
412 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000413 Cop = o.Cop;
414 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000415 case k_CoprocOption:
416 CoprocOption = o.CoprocOption;
417 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000418 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000419 Imm = o.Imm;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000422 FPImm = o.FPImm;
423 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000424 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000425 MBOpt = o.MBOpt;
426 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000427 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000428 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000431 PostIdxReg = o.PostIdxReg;
432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000434 MMask = o.MMask;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000437 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000440 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000443 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000446 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000449 RotImm = o.RotImm;
450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000452 Bitfield = o.Bitfield;
453 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000454 case k_VectorIndex:
455 VectorIndex = o.VectorIndex;
456 break;
Sean Callanan76264762010-04-02 22:27:05 +0000457 }
458 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000459
Sean Callanan76264762010-04-02 22:27:05 +0000460 /// getStartLoc - Get the location of the first token of this operand.
461 SMLoc getStartLoc() const { return StartLoc; }
462 /// getEndLoc - Get the location of the last token of this operand.
463 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000464
Daniel Dunbar8462b302010-08-11 06:36:53 +0000465 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000466 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000467 return CC.Val;
468 }
469
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000470 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000472 return Cop.Val;
473 }
474
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000475 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000476 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000477 return StringRef(Tok.Data, Tok.Length);
478 }
479
480 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000481 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000482 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000483 }
484
Bill Wendling5fa22a12010-11-09 23:28:44 +0000485 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000486 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
487 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000488 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000489 }
490
Kevin Enderbycfe07242009-10-13 22:19:02 +0000491 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000493 return Imm.Val;
494 }
495
Jim Grosbach9d390362011-10-03 23:38:36 +0000496 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000497 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000498 return FPImm.Val;
499 }
500
Jim Grosbach460a9052011-10-07 23:56:00 +0000501 unsigned getVectorIndex() const {
502 assert(Kind == k_VectorIndex && "Invalid access!");
503 return VectorIndex.Val;
504 }
505
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000506 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000507 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000508 return MBOpt.Val;
509 }
510
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000511 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000512 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000513 return IFlags.Val;
514 }
515
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000516 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000517 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000518 return MMask.Val;
519 }
520
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000521 bool isCoprocNum() const { return Kind == k_CoprocNum; }
522 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000523 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 bool isCondCode() const { return Kind == k_CondCode; }
525 bool isCCOut() const { return Kind == k_CCOut; }
526 bool isITMask() const { return Kind == k_ITCondMask; }
527 bool isITCondCode() const { return Kind == k_CondCode; }
528 bool isImm() const { return Kind == k_Immediate; }
529 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000530 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000531 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000532 return false;
533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
534 if (!CE) return false;
535 int64_t Value = CE->getValue();
536 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
537 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000538 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000539 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000540 return false;
541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
542 if (!CE) return false;
543 int64_t Value = CE->getValue();
544 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
545 }
546 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000547 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000548 return false;
549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
550 if (!CE) return false;
551 int64_t Value = CE->getValue();
552 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
553 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000554 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000555 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000556 return false;
557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
558 if (!CE) return false;
559 int64_t Value = CE->getValue();
560 return Value >= 0 && Value < 256;
561 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000562 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000563 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000564 return false;
565 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
566 if (!CE) return false;
567 int64_t Value = CE->getValue();
568 return Value >= 0 && Value < 8;
569 }
570 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000571 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000572 return false;
573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return Value >= 0 && Value < 16;
577 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000578 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000579 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000580 return false;
581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
582 if (!CE) return false;
583 int64_t Value = CE->getValue();
584 return Value >= 0 && Value < 32;
585 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000586 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000587 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000588 return false;
589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
590 if (!CE) return false;
591 int64_t Value = CE->getValue();
592 return Value > 0 && Value < 17;
593 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000594 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000595 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000596 return false;
597 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
598 if (!CE) return false;
599 int64_t Value = CE->getValue();
600 return Value > 0 && Value < 33;
601 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000602 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000603 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000604 return false;
605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
606 if (!CE) return false;
607 int64_t Value = CE->getValue();
608 return Value >= 0 && Value < 65536;
609 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000610 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000611 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000612 return false;
613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
614 // If it's not a constant expression, it'll generate a fixup and be
615 // handled later.
616 if (!CE) return true;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 65536;
619 }
Jim Grosbached838482011-07-26 16:24:27 +0000620 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000621 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000622 return false;
623 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
624 if (!CE) return false;
625 int64_t Value = CE->getValue();
626 return Value >= 0 && Value <= 0xffffff;
627 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000628 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000629 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000630 return false;
631 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
632 if (!CE) return false;
633 int64_t Value = CE->getValue();
634 return Value > 0 && Value < 33;
635 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000636 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000637 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000638 return false;
639 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
640 if (!CE) return false;
641 int64_t Value = CE->getValue();
642 return Value >= 0 && Value < 32;
643 }
644 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000645 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000646 return false;
647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
648 if (!CE) return false;
649 int64_t Value = CE->getValue();
650 return Value > 0 && Value <= 32;
651 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000652 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000653 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000654 return false;
655 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
656 if (!CE) return false;
657 int64_t Value = CE->getValue();
658 return ARM_AM::getSOImmVal(Value) != -1;
659 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000660 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000661 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000662 return false;
663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
664 if (!CE) return false;
665 int64_t Value = CE->getValue();
666 return ARM_AM::getT2SOImmVal(Value) != -1;
667 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000668 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000669 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000670 return false;
671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return Value == 1 || Value == 0;
675 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000676 bool isReg() const { return Kind == k_Register; }
677 bool isRegList() const { return Kind == k_RegisterList; }
678 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
679 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
680 bool isToken() const { return Kind == k_Token; }
681 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
682 bool isMemory() const { return Kind == k_Memory; }
683 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
684 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
685 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
686 bool isRotImm() const { return Kind == k_RotateImmediate; }
687 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
688 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000689 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000690 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000691 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000692 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000693 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000694 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000695 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000696 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
697 (alignOK || Memory.Alignment == 0);
698 }
699 bool isAlignedMemory() const {
700 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000701 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000702 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000703 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000704 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000705 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000706 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000707 if (!Memory.OffsetImm) return true;
708 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000709 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000710 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000711 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000712 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000713 return false;
714 // Immediate offset in range [-4095, 4095].
715 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
716 if (!CE) return false;
717 int64_t Val = CE->getValue();
718 return Val > -4096 && Val < 4096;
719 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000720 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000721 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000722 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000723 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000724 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000725 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000726 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000727 if (!Memory.OffsetImm) return true;
728 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000729 return Val > -256 && Val < 256;
730 }
731 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000732 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000733 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000734 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000735 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
736 // Immediate offset in range [-255, 255].
737 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
738 if (!CE) return false;
739 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000740 // Special case, #-0 is INT32_MIN.
741 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000742 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000743 bool isAddrMode5() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000744 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000745 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000746 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000747 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000748 if (!Memory.OffsetImm) return true;
749 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000750 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
751 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000752 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000753 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000754 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000755 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000756 return false;
757 return true;
758 }
759 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000760 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000761 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
762 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000763 return false;
764 return true;
765 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000766 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000767 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000768 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000769 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000770 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000771 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000772 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
773 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000774 return false;
775 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000776 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000777 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000778 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000779 return false;
780 return true;
781 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000782 bool isMemThumbRR() const {
783 // Thumb reg+reg addressing is simple. Just two registers, a base and
784 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000785 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000786 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000787 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000788 return isARMLowRegister(Memory.BaseRegNum) &&
789 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000790 }
791 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000792 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000793 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000794 return false;
795 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000796 if (!Memory.OffsetImm) return true;
797 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000798 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
799 }
Jim Grosbach38466302011-08-19 18:55:51 +0000800 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000801 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000802 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000803 return false;
804 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000805 if (!Memory.OffsetImm) return true;
806 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000807 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
808 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000809 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000810 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000811 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000812 return false;
813 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000814 if (!Memory.OffsetImm) return true;
815 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000816 return Val >= 0 && Val <= 31;
817 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000818 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000819 if (!isMemory() || Memory.OffsetRegNum != 0 ||
820 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000821 return false;
822 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000823 if (!Memory.OffsetImm) return true;
824 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000825 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000826 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000827 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000828 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000829 return false;
830 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000831 if (!Memory.OffsetImm) return true;
832 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000833 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
834 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000835 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000836 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000837 return false;
838 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000839 if (!Memory.OffsetImm) return true;
840 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000841 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
842 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000843 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000844 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000845 return false;
846 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000847 if (!Memory.OffsetImm) return true;
848 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000849 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000850 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000851 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000852 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000853 return false;
854 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000857 return Val >= 0 && Val < 256;
858 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000859 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000861 return false;
862 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000865 return Val > -256 && Val < 0;
866 }
867 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000869 return false;
870 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000873 return (Val >= 0 && Val < 4096);
874 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000875 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000876 // If we have an immediate that's not a constant, treat it as a label
877 // reference needing a fixup. If it is a constant, it's something else
878 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000879 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000880 return true;
881
Jim Grosbach57dcb852011-10-11 17:29:55 +0000882 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000883 return false;
884 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000885 if (!Memory.OffsetImm) return true;
886 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000887 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000888 }
889 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000890 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000891 return false;
892 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
893 if (!CE) return false;
894 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000895 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000896 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000897 bool isPostIdxImm8s4() const {
898 if (Kind != k_Immediate)
899 return false;
900 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
901 if (!CE) return false;
902 int64_t Val = CE->getValue();
903 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
904 (Val == INT32_MIN);
905 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000906
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000907 bool isMSRMask() const { return Kind == k_MSRMask; }
908 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000909
Jim Grosbach0e387b22011-10-17 22:26:03 +0000910 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000911 bool isVecListOneD() const {
912 if (Kind != k_VectorList) return false;
913 return VectorList.Count == 1;
914 }
915
Jim Grosbach280dfad2011-10-21 18:54:25 +0000916 bool isVecListTwoD() const {
917 if (Kind != k_VectorList) return false;
918 return VectorList.Count == 2;
919 }
920
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000921 bool isVecListThreeD() const {
922 if (Kind != k_VectorList) return false;
923 return VectorList.Count == 3;
924 }
925
Jim Grosbachb6310312011-10-21 20:35:01 +0000926 bool isVecListFourD() const {
927 if (Kind != k_VectorList) return false;
928 return VectorList.Count == 4;
929 }
930
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000931 bool isVecListTwoQ() const {
932 if (Kind != k_VectorList) return false;
933 //FIXME: We haven't taught the parser to handle by-two register lists
934 // yet, so don't pretend to know one.
935 return VectorList.Count == 2 && false;
936 }
937
Jim Grosbach460a9052011-10-07 23:56:00 +0000938 bool isVectorIndex8() const {
939 if (Kind != k_VectorIndex) return false;
940 return VectorIndex.Val < 8;
941 }
942 bool isVectorIndex16() const {
943 if (Kind != k_VectorIndex) return false;
944 return VectorIndex.Val < 4;
945 }
946 bool isVectorIndex32() const {
947 if (Kind != k_VectorIndex) return false;
948 return VectorIndex.Val < 2;
949 }
950
Jim Grosbach0e387b22011-10-17 22:26:03 +0000951 bool isNEONi8splat() const {
952 if (Kind != k_Immediate)
953 return false;
954 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
955 // Must be a constant.
956 if (!CE) return false;
957 int64_t Value = CE->getValue();
958 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
959 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000960 return Value >= 0 && Value < 256;
961 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000962
Jim Grosbachea461102011-10-17 23:09:09 +0000963 bool isNEONi16splat() const {
964 if (Kind != k_Immediate)
965 return false;
966 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
967 // Must be a constant.
968 if (!CE) return false;
969 int64_t Value = CE->getValue();
970 // i16 value in the range [0,255] or [0x0100, 0xff00]
971 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
972 }
973
Jim Grosbach6248a542011-10-18 00:22:00 +0000974 bool isNEONi32splat() const {
975 if (Kind != k_Immediate)
976 return false;
977 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
978 // Must be a constant.
979 if (!CE) return false;
980 int64_t Value = CE->getValue();
981 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
982 return (Value >= 0 && Value < 256) ||
983 (Value >= 0x0100 && Value <= 0xff00) ||
984 (Value >= 0x010000 && Value <= 0xff0000) ||
985 (Value >= 0x01000000 && Value <= 0xff000000);
986 }
987
988 bool isNEONi32vmov() const {
989 if (Kind != k_Immediate)
990 return false;
991 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
992 // Must be a constant.
993 if (!CE) return false;
994 int64_t Value = CE->getValue();
995 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
996 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
997 return (Value >= 0 && Value < 256) ||
998 (Value >= 0x0100 && Value <= 0xff00) ||
999 (Value >= 0x010000 && Value <= 0xff0000) ||
1000 (Value >= 0x01000000 && Value <= 0xff000000) ||
1001 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1002 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1003 }
1004
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001005 bool isNEONi64splat() const {
1006 if (Kind != k_Immediate)
1007 return false;
1008 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1009 // Must be a constant.
1010 if (!CE) return false;
1011 uint64_t Value = CE->getValue();
1012 // i64 value with each byte being either 0 or 0xff.
1013 for (unsigned i = 0; i < 8; ++i)
1014 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1015 return true;
1016 }
1017
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001018 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001019 // Add as immediates when possible. Null MCExpr = 0.
1020 if (Expr == 0)
1021 Inst.addOperand(MCOperand::CreateImm(0));
1022 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001023 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1024 else
1025 Inst.addOperand(MCOperand::CreateExpr(Expr));
1026 }
1027
Daniel Dunbar8462b302010-08-11 06:36:53 +00001028 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001029 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001030 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001031 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1032 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001033 }
1034
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001035 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1036 assert(N == 1 && "Invalid number of operands!");
1037 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1038 }
1039
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001040 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1041 assert(N == 1 && "Invalid number of operands!");
1042 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1043 }
1044
1045 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1046 assert(N == 1 && "Invalid number of operands!");
1047 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1048 }
1049
Jim Grosbach89df9962011-08-26 21:43:41 +00001050 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1051 assert(N == 1 && "Invalid number of operands!");
1052 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1053 }
1054
1055 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1056 assert(N == 1 && "Invalid number of operands!");
1057 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1058 }
1059
Jim Grosbachd67641b2010-12-06 18:21:12 +00001060 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1061 assert(N == 1 && "Invalid number of operands!");
1062 Inst.addOperand(MCOperand::CreateReg(getReg()));
1063 }
1064
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001065 void addRegOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!");
1067 Inst.addOperand(MCOperand::CreateReg(getReg()));
1068 }
1069
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001070 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001071 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001072 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1073 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1074 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001075 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001076 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001077 }
1078
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001079 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001080 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001081 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1082 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001083 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001084 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001085 }
1086
Jim Grosbach580f4a92011-07-25 22:20:28 +00001087 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001088 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001089 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1090 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001091 }
1092
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001093 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001094 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001095 const SmallVectorImpl<unsigned> &RegList = getRegList();
1096 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001097 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1098 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001099 }
1100
Bill Wendling0f630752010-11-17 04:32:08 +00001101 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1102 addRegListOperands(Inst, N);
1103 }
1104
1105 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1106 addRegListOperands(Inst, N);
1107 }
1108
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001109 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1110 assert(N == 1 && "Invalid number of operands!");
1111 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1112 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1113 }
1114
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001115 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1116 assert(N == 1 && "Invalid number of operands!");
1117 // Munge the lsb/width into a bitfield mask.
1118 unsigned lsb = Bitfield.LSB;
1119 unsigned width = Bitfield.Width;
1120 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1121 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1122 (32 - (lsb + width)));
1123 Inst.addOperand(MCOperand::CreateImm(Mask));
1124 }
1125
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001126 void addImmOperands(MCInst &Inst, unsigned N) const {
1127 assert(N == 1 && "Invalid number of operands!");
1128 addExpr(Inst, getImm());
1129 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001130
Jim Grosbach9d390362011-10-03 23:38:36 +00001131 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1132 assert(N == 1 && "Invalid number of operands!");
1133 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1134 }
1135
Jim Grosbacha77295d2011-09-08 22:07:06 +00001136 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1137 assert(N == 1 && "Invalid number of operands!");
1138 // FIXME: We really want to scale the value here, but the LDRD/STRD
1139 // instruction don't encode operands that way yet.
1140 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1141 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1142 }
1143
Jim Grosbach72f39f82011-08-24 21:22:15 +00001144 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1145 assert(N == 1 && "Invalid number of operands!");
1146 // The immediate is scaled by four in the encoding and is stored
1147 // in the MCInst as such. Lop off the low two bits here.
1148 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1149 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1150 }
1151
1152 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
1154 // The immediate is scaled by four in the encoding and is stored
1155 // in the MCInst as such. Lop off the low two bits here.
1156 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1157 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1158 }
1159
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001160 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 addExpr(Inst, getImm());
1163 }
1164
Jim Grosbach83ab0702011-07-13 22:01:08 +00001165 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
1167 addExpr(Inst, getImm());
1168 }
1169
1170 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 addExpr(Inst, getImm());
1173 }
1174
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001175 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1176 assert(N == 1 && "Invalid number of operands!");
1177 addExpr(Inst, getImm());
1178 }
1179
Jim Grosbachf4943352011-07-25 23:09:14 +00001180 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
1182 // The constant encodes as the immediate-1, and we store in the instruction
1183 // the bits as encoded, so subtract off one here.
1184 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1185 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1186 }
1187
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001188 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1189 assert(N == 1 && "Invalid number of operands!");
1190 // The constant encodes as the immediate-1, and we store in the instruction
1191 // the bits as encoded, so subtract off one here.
1192 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1193 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1194 }
1195
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001196 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
1198 addExpr(Inst, getImm());
1199 }
1200
Jim Grosbachffa32252011-07-19 19:13:28 +00001201 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 1 && "Invalid number of operands!");
1203 addExpr(Inst, getImm());
1204 }
1205
Jim Grosbached838482011-07-26 16:24:27 +00001206 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1207 assert(N == 1 && "Invalid number of operands!");
1208 addExpr(Inst, getImm());
1209 }
1210
Jim Grosbach70939ee2011-08-17 21:51:27 +00001211 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 1 && "Invalid number of operands!");
1213 // The constant encodes as the immediate, except for 32, which encodes as
1214 // zero.
1215 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1216 unsigned Imm = CE->getValue();
1217 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1218 }
1219
Jim Grosbachf6c05252011-07-21 17:23:04 +00001220 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1221 assert(N == 1 && "Invalid number of operands!");
1222 addExpr(Inst, getImm());
1223 }
1224
1225 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1226 assert(N == 1 && "Invalid number of operands!");
1227 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1228 // the instruction as well.
1229 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1230 int Val = CE->getValue();
1231 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1232 }
1233
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001234 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1235 assert(N == 1 && "Invalid number of operands!");
1236 addExpr(Inst, getImm());
1237 }
1238
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001239 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1240 assert(N == 1 && "Invalid number of operands!");
1241 addExpr(Inst, getImm());
1242 }
1243
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001244 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 1 && "Invalid number of operands!");
1246 addExpr(Inst, getImm());
1247 }
1248
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001249 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
1251 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1252 }
1253
Jim Grosbach7ce05792011-08-03 23:50:40 +00001254 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001256 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001257 }
1258
Jim Grosbach57dcb852011-10-11 17:29:55 +00001259 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1260 assert(N == 2 && "Invalid number of operands!");
1261 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1262 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1263 }
1264
Jim Grosbach7ce05792011-08-03 23:50:40 +00001265 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1266 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001267 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1268 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001269 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1270 // Special case for #-0
1271 if (Val == INT32_MIN) Val = 0;
1272 if (Val < 0) Val = -Val;
1273 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1274 } else {
1275 // For register offset, we encode the shift type and negation flag
1276 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001277 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1278 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001279 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001280 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1281 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001282 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001283 }
1284
Jim Grosbach039c2e12011-08-04 23:01:30 +00001285 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1286 assert(N == 2 && "Invalid number of operands!");
1287 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1288 assert(CE && "non-constant AM2OffsetImm operand!");
1289 int32_t Val = CE->getValue();
1290 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1291 // Special case for #-0
1292 if (Val == INT32_MIN) Val = 0;
1293 if (Val < 0) Val = -Val;
1294 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1295 Inst.addOperand(MCOperand::CreateReg(0));
1296 Inst.addOperand(MCOperand::CreateImm(Val));
1297 }
1298
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001299 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1300 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001301 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1302 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001303 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1304 // Special case for #-0
1305 if (Val == INT32_MIN) Val = 0;
1306 if (Val < 0) Val = -Val;
1307 Val = ARM_AM::getAM3Opc(AddSub, Val);
1308 } else {
1309 // For register offset, we encode the shift type and negation flag
1310 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001311 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001312 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001313 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1314 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001315 Inst.addOperand(MCOperand::CreateImm(Val));
1316 }
1317
1318 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1319 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001320 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001321 int32_t Val =
1322 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1323 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1324 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001325 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001326 }
1327
1328 // Constant offset.
1329 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1330 int32_t Val = CE->getValue();
1331 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1332 // Special case for #-0
1333 if (Val == INT32_MIN) Val = 0;
1334 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001335 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001336 Inst.addOperand(MCOperand::CreateReg(0));
1337 Inst.addOperand(MCOperand::CreateImm(Val));
1338 }
1339
Jim Grosbach7ce05792011-08-03 23:50:40 +00001340 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1341 assert(N == 2 && "Invalid number of operands!");
1342 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001343 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001344 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1345 // Special case for #-0
1346 if (Val == INT32_MIN) Val = 0;
1347 if (Val < 0) Val = -Val;
1348 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001349 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001350 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001351 }
1352
Jim Grosbacha77295d2011-09-08 22:07:06 +00001353 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1354 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001355 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1356 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001357 Inst.addOperand(MCOperand::CreateImm(Val));
1358 }
1359
Jim Grosbachb6aed502011-09-09 18:37:27 +00001360 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1361 assert(N == 2 && "Invalid number of operands!");
1362 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001363 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1364 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001365 Inst.addOperand(MCOperand::CreateImm(Val));
1366 }
1367
Jim Grosbach7ce05792011-08-03 23:50:40 +00001368 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001370 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1371 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001372 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001373 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001374
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001375 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1376 addMemImm8OffsetOperands(Inst, N);
1377 }
1378
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001379 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001380 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001381 }
1382
1383 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 2 && "Invalid number of operands!");
1385 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001386 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001387 addExpr(Inst, getImm());
1388 Inst.addOperand(MCOperand::CreateImm(0));
1389 return;
1390 }
1391
1392 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001393 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1394 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001395 Inst.addOperand(MCOperand::CreateImm(Val));
1396 }
1397
Jim Grosbach7ce05792011-08-03 23:50:40 +00001398 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1399 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001400 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001401 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001402 addExpr(Inst, getImm());
1403 Inst.addOperand(MCOperand::CreateImm(0));
1404 return;
1405 }
1406
1407 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001408 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1409 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001410 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001411 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001412
Jim Grosbach7f739be2011-09-19 22:21:13 +00001413 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1414 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001415 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1416 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001417 }
1418
1419 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001421 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1422 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001423 }
1424
Jim Grosbach7ce05792011-08-03 23:50:40 +00001425 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1426 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001427 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1428 Memory.ShiftImm, Memory.ShiftType);
1429 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1430 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001431 Inst.addOperand(MCOperand::CreateImm(Val));
1432 }
1433
Jim Grosbachab899c12011-09-07 23:10:15 +00001434 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001436 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1437 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1438 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001439 }
1440
Jim Grosbach7ce05792011-08-03 23:50:40 +00001441 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001443 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1444 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001445 }
1446
Jim Grosbach60f91a32011-08-19 17:55:24 +00001447 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1448 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001449 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1450 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001451 Inst.addOperand(MCOperand::CreateImm(Val));
1452 }
1453
Jim Grosbach38466302011-08-19 18:55:51 +00001454 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1455 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001456 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1457 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001458 Inst.addOperand(MCOperand::CreateImm(Val));
1459 }
1460
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001461 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1462 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001463 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1464 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001465 Inst.addOperand(MCOperand::CreateImm(Val));
1466 }
1467
Jim Grosbachecd85892011-08-19 18:13:48 +00001468 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1469 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001470 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1471 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001472 Inst.addOperand(MCOperand::CreateImm(Val));
1473 }
1474
Jim Grosbach7ce05792011-08-03 23:50:40 +00001475 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1478 assert(CE && "non-constant post-idx-imm8 operand!");
1479 int Imm = CE->getValue();
1480 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001481 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001482 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1483 Inst.addOperand(MCOperand::CreateImm(Imm));
1484 }
1485
Jim Grosbach2bd01182011-10-11 21:55:36 +00001486 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1489 assert(CE && "non-constant post-idx-imm8s4 operand!");
1490 int Imm = CE->getValue();
1491 bool isAdd = Imm >= 0;
1492 if (Imm == INT32_MIN) Imm = 0;
1493 // Immediate is scaled by 4.
1494 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1495 Inst.addOperand(MCOperand::CreateImm(Imm));
1496 }
1497
Jim Grosbach7ce05792011-08-03 23:50:40 +00001498 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1499 assert(N == 2 && "Invalid number of operands!");
1500 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001501 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1502 }
1503
1504 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 2 && "Invalid number of operands!");
1506 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1507 // The sign, shift type, and shift amount are encoded in a single operand
1508 // using the AM2 encoding helpers.
1509 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1510 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1511 PostIdxReg.ShiftTy);
1512 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001513 }
1514
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001515 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1516 assert(N == 1 && "Invalid number of operands!");
1517 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1518 }
1519
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001520 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
1522 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1523 }
1524
Jim Grosbach862019c2011-10-18 23:02:30 +00001525 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
1527 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1528 }
1529
Jim Grosbach280dfad2011-10-21 18:54:25 +00001530 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 1 && "Invalid number of operands!");
1532 // Only the first register actually goes on the instruction. The rest
1533 // are implied by the opcode.
1534 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1535 }
1536
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001537 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1538 assert(N == 1 && "Invalid number of operands!");
1539 // Only the first register actually goes on the instruction. The rest
1540 // are implied by the opcode.
1541 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1542 }
1543
Jim Grosbachb6310312011-10-21 20:35:01 +00001544 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1545 assert(N == 1 && "Invalid number of operands!");
1546 // Only the first register actually goes on the instruction. The rest
1547 // are implied by the opcode.
1548 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1549 }
1550
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001551 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1552 assert(N == 1 && "Invalid number of operands!");
1553 // Only the first register actually goes on the instruction. The rest
1554 // are implied by the opcode.
1555 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1556 }
1557
Jim Grosbach460a9052011-10-07 23:56:00 +00001558 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1559 assert(N == 1 && "Invalid number of operands!");
1560 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1561 }
1562
1563 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1564 assert(N == 1 && "Invalid number of operands!");
1565 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1566 }
1567
1568 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
1570 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1571 }
1572
Jim Grosbach0e387b22011-10-17 22:26:03 +00001573 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 // The immediate encodes the type of constant as well as the value.
1576 // Mask in that this is an i8 splat.
1577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1578 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1579 }
1580
Jim Grosbachea461102011-10-17 23:09:09 +00001581 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1582 assert(N == 1 && "Invalid number of operands!");
1583 // The immediate encodes the type of constant as well as the value.
1584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1585 unsigned Value = CE->getValue();
1586 if (Value >= 256)
1587 Value = (Value >> 8) | 0xa00;
1588 else
1589 Value |= 0x800;
1590 Inst.addOperand(MCOperand::CreateImm(Value));
1591 }
1592
Jim Grosbach6248a542011-10-18 00:22:00 +00001593 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1594 assert(N == 1 && "Invalid number of operands!");
1595 // The immediate encodes the type of constant as well as the value.
1596 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1597 unsigned Value = CE->getValue();
1598 if (Value >= 256 && Value <= 0xff00)
1599 Value = (Value >> 8) | 0x200;
1600 else if (Value > 0xffff && Value <= 0xff0000)
1601 Value = (Value >> 16) | 0x400;
1602 else if (Value > 0xffffff)
1603 Value = (Value >> 24) | 0x600;
1604 Inst.addOperand(MCOperand::CreateImm(Value));
1605 }
1606
1607 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1608 assert(N == 1 && "Invalid number of operands!");
1609 // The immediate encodes the type of constant as well as the value.
1610 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1611 unsigned Value = CE->getValue();
1612 if (Value >= 256 && Value <= 0xffff)
1613 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1614 else if (Value > 0xffff && Value <= 0xffffff)
1615 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1616 else if (Value > 0xffffff)
1617 Value = (Value >> 24) | 0x600;
1618 Inst.addOperand(MCOperand::CreateImm(Value));
1619 }
1620
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001621 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1622 assert(N == 1 && "Invalid number of operands!");
1623 // The immediate encodes the type of constant as well as the value.
1624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1625 uint64_t Value = CE->getValue();
1626 unsigned Imm = 0;
1627 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1628 Imm |= (Value & 1) << i;
1629 }
1630 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1631 }
1632
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001633 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001634
Jim Grosbach89df9962011-08-26 21:43:41 +00001635 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001636 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001637 Op->ITMask.Mask = Mask;
1638 Op->StartLoc = S;
1639 Op->EndLoc = S;
1640 return Op;
1641 }
1642
Chris Lattner3a697562010-10-28 17:20:03 +00001643 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001644 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001645 Op->CC.Val = CC;
1646 Op->StartLoc = S;
1647 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001648 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001649 }
1650
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001651 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001652 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001653 Op->Cop.Val = CopVal;
1654 Op->StartLoc = S;
1655 Op->EndLoc = S;
1656 return Op;
1657 }
1658
1659 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001660 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001661 Op->Cop.Val = CopVal;
1662 Op->StartLoc = S;
1663 Op->EndLoc = S;
1664 return Op;
1665 }
1666
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001667 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1668 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1669 Op->Cop.Val = Val;
1670 Op->StartLoc = S;
1671 Op->EndLoc = E;
1672 return Op;
1673 }
1674
Jim Grosbachd67641b2010-12-06 18:21:12 +00001675 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001676 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001677 Op->Reg.RegNum = RegNum;
1678 Op->StartLoc = S;
1679 Op->EndLoc = S;
1680 return Op;
1681 }
1682
Chris Lattner3a697562010-10-28 17:20:03 +00001683 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001684 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001685 Op->Tok.Data = Str.data();
1686 Op->Tok.Length = Str.size();
1687 Op->StartLoc = S;
1688 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001689 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001690 }
1691
Bill Wendling50d0f582010-11-18 23:43:05 +00001692 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001693 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001694 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001695 Op->StartLoc = S;
1696 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001697 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001698 }
1699
Jim Grosbache8606dc2011-07-13 17:50:29 +00001700 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1701 unsigned SrcReg,
1702 unsigned ShiftReg,
1703 unsigned ShiftImm,
1704 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001705 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001706 Op->RegShiftedReg.ShiftTy = ShTy;
1707 Op->RegShiftedReg.SrcReg = SrcReg;
1708 Op->RegShiftedReg.ShiftReg = ShiftReg;
1709 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001710 Op->StartLoc = S;
1711 Op->EndLoc = E;
1712 return Op;
1713 }
1714
Owen Anderson92a20222011-07-21 18:54:16 +00001715 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1716 unsigned SrcReg,
1717 unsigned ShiftImm,
1718 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001719 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001720 Op->RegShiftedImm.ShiftTy = ShTy;
1721 Op->RegShiftedImm.SrcReg = SrcReg;
1722 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001723 Op->StartLoc = S;
1724 Op->EndLoc = E;
1725 return Op;
1726 }
1727
Jim Grosbach580f4a92011-07-25 22:20:28 +00001728 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001729 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001730 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001731 Op->ShifterImm.isASR = isASR;
1732 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001733 Op->StartLoc = S;
1734 Op->EndLoc = E;
1735 return Op;
1736 }
1737
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001738 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001739 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001740 Op->RotImm.Imm = Imm;
1741 Op->StartLoc = S;
1742 Op->EndLoc = E;
1743 return Op;
1744 }
1745
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001746 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1747 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001748 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001749 Op->Bitfield.LSB = LSB;
1750 Op->Bitfield.Width = Width;
1751 Op->StartLoc = S;
1752 Op->EndLoc = E;
1753 return Op;
1754 }
1755
Bill Wendling7729e062010-11-09 22:44:22 +00001756 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001757 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001758 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001759 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001760
Jim Grosbachd300b942011-09-13 22:56:44 +00001761 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001762 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001763 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001764 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001765 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001766
1767 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001768 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001769 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001770 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001771 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001772 Op->StartLoc = StartLoc;
1773 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001774 return Op;
1775 }
1776
Jim Grosbach862019c2011-10-18 23:02:30 +00001777 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1778 SMLoc S, SMLoc E) {
1779 ARMOperand *Op = new ARMOperand(k_VectorList);
1780 Op->VectorList.RegNum = RegNum;
1781 Op->VectorList.Count = Count;
1782 Op->StartLoc = S;
1783 Op->EndLoc = E;
1784 return Op;
1785 }
1786
Jim Grosbach460a9052011-10-07 23:56:00 +00001787 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1788 MCContext &Ctx) {
1789 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1790 Op->VectorIndex.Val = Idx;
1791 Op->StartLoc = S;
1792 Op->EndLoc = E;
1793 return Op;
1794 }
1795
Chris Lattner3a697562010-10-28 17:20:03 +00001796 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001797 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001798 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001799 Op->StartLoc = S;
1800 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001801 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001802 }
1803
Jim Grosbach9d390362011-10-03 23:38:36 +00001804 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001805 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001806 Op->FPImm.Val = Val;
1807 Op->StartLoc = S;
1808 Op->EndLoc = S;
1809 return Op;
1810 }
1811
Jim Grosbach7ce05792011-08-03 23:50:40 +00001812 static ARMOperand *CreateMem(unsigned BaseRegNum,
1813 const MCConstantExpr *OffsetImm,
1814 unsigned OffsetRegNum,
1815 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001816 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001817 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001818 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001819 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001820 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001821 Op->Memory.BaseRegNum = BaseRegNum;
1822 Op->Memory.OffsetImm = OffsetImm;
1823 Op->Memory.OffsetRegNum = OffsetRegNum;
1824 Op->Memory.ShiftType = ShiftType;
1825 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001826 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001827 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001828 Op->StartLoc = S;
1829 Op->EndLoc = E;
1830 return Op;
1831 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001832
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001833 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1834 ARM_AM::ShiftOpc ShiftTy,
1835 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001836 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001837 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001838 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001839 Op->PostIdxReg.isAdd = isAdd;
1840 Op->PostIdxReg.ShiftTy = ShiftTy;
1841 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001842 Op->StartLoc = S;
1843 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001844 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001845 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001846
1847 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001848 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001849 Op->MBOpt.Val = Opt;
1850 Op->StartLoc = S;
1851 Op->EndLoc = S;
1852 return Op;
1853 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001854
1855 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001856 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001857 Op->IFlags.Val = IFlags;
1858 Op->StartLoc = S;
1859 Op->EndLoc = S;
1860 return Op;
1861 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001862
1863 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001864 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001865 Op->MMask.Val = MMask;
1866 Op->StartLoc = S;
1867 Op->EndLoc = S;
1868 return Op;
1869 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001870};
1871
1872} // end anonymous namespace.
1873
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001874void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001875 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001876 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001877 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1878 << ") >";
1879 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001880 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001881 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001882 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001883 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001884 OS << "<ccout " << getReg() << ">";
1885 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001886 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001887 static const char *MaskStr[] = {
1888 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1889 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1890 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001891 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1892 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1893 break;
1894 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001895 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001896 OS << "<coprocessor number: " << getCoproc() << ">";
1897 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001898 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001899 OS << "<coprocessor register: " << getCoproc() << ">";
1900 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001901 case k_CoprocOption:
1902 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1903 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001904 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001905 OS << "<mask: " << getMSRMask() << ">";
1906 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001907 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001908 getImm()->print(OS);
1909 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001910 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001911 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1912 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001913 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001914 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001915 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001916 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001917 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001918 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001919 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1920 << PostIdxReg.RegNum;
1921 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1922 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1923 << PostIdxReg.ShiftImm;
1924 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001925 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001926 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001927 OS << "<ARM_PROC::";
1928 unsigned IFlags = getProcIFlags();
1929 for (int i=2; i >= 0; --i)
1930 if (IFlags & (1 << i))
1931 OS << ARM_PROC::IFlagsToString(1 << i);
1932 OS << ">";
1933 break;
1934 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001935 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001936 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001937 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001938 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001939 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1940 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001941 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001942 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001943 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001944 << RegShiftedReg.SrcReg
1945 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1946 << ", " << RegShiftedReg.ShiftReg << ", "
1947 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001948 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001949 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001950 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001951 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001952 << RegShiftedImm.SrcReg
1953 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1954 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001955 << ">";
1956 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001957 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001958 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1959 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001960 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001961 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1962 << ", width: " << Bitfield.Width << ">";
1963 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001964 case k_RegisterList:
1965 case k_DPRRegisterList:
1966 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001967 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001968
Bill Wendling5fa22a12010-11-09 23:28:44 +00001969 const SmallVectorImpl<unsigned> &RegList = getRegList();
1970 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001971 I = RegList.begin(), E = RegList.end(); I != E; ) {
1972 OS << *I;
1973 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001974 }
1975
1976 OS << ">";
1977 break;
1978 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001979 case k_VectorList:
1980 OS << "<vector_list " << VectorList.Count << " * "
1981 << VectorList.RegNum << ">";
1982 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001983 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001984 OS << "'" << getToken() << "'";
1985 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001986 case k_VectorIndex:
1987 OS << "<vectorindex " << getVectorIndex() << ">";
1988 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001989 }
1990}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001991
1992/// @name Auto-generated Match Functions
1993/// {
1994
1995static unsigned MatchRegisterName(StringRef Name);
1996
1997/// }
1998
Bob Wilson69df7232011-02-03 21:46:10 +00001999bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2000 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002001 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002002
2003 return (RegNo == (unsigned)-1);
2004}
2005
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002006/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002007/// and if it is a register name the token is eaten and the register number is
2008/// returned. Otherwise return -1.
2009///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002010int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002011 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002012 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002013
Chris Lattnere5658fa2010-10-30 04:09:10 +00002014 // FIXME: Validate register for the current architecture; we have to do
2015 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00002016 std::string upperCase = Tok.getString().str();
2017 std::string lowerCase = LowercaseString(upperCase);
2018 unsigned RegNum = MatchRegisterName(lowerCase);
2019 if (!RegNum) {
2020 RegNum = StringSwitch<unsigned>(lowerCase)
2021 .Case("r13", ARM::SP)
2022 .Case("r14", ARM::LR)
2023 .Case("r15", ARM::PC)
2024 .Case("ip", ARM::R12)
2025 .Default(0);
2026 }
2027 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002028
Chris Lattnere5658fa2010-10-30 04:09:10 +00002029 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002030
Chris Lattnere5658fa2010-10-30 04:09:10 +00002031 return RegNum;
2032}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002033
Jim Grosbach19906722011-07-13 18:49:30 +00002034// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2035// If a recoverable error occurs, return 1. If an irrecoverable error
2036// occurs, return -1. An irrecoverable error is one where tokens have been
2037// consumed in the process of trying to parse the shifter (i.e., when it is
2038// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002039int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002040 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2041 SMLoc S = Parser.getTok().getLoc();
2042 const AsmToken &Tok = Parser.getTok();
2043 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2044
2045 std::string upperCase = Tok.getString().str();
2046 std::string lowerCase = LowercaseString(upperCase);
2047 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2048 .Case("lsl", ARM_AM::lsl)
2049 .Case("lsr", ARM_AM::lsr)
2050 .Case("asr", ARM_AM::asr)
2051 .Case("ror", ARM_AM::ror)
2052 .Case("rrx", ARM_AM::rrx)
2053 .Default(ARM_AM::no_shift);
2054
2055 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002056 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002057
Jim Grosbache8606dc2011-07-13 17:50:29 +00002058 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002059
Jim Grosbache8606dc2011-07-13 17:50:29 +00002060 // The source register for the shift has already been added to the
2061 // operand list, so we need to pop it off and combine it into the shifted
2062 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002063 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002064 if (!PrevOp->isReg())
2065 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2066 int SrcReg = PrevOp->getReg();
2067 int64_t Imm = 0;
2068 int ShiftReg = 0;
2069 if (ShiftTy == ARM_AM::rrx) {
2070 // RRX Doesn't have an explicit shift amount. The encoder expects
2071 // the shift register to be the same as the source register. Seems odd,
2072 // but OK.
2073 ShiftReg = SrcReg;
2074 } else {
2075 // Figure out if this is shifted by a constant or a register (for non-RRX).
2076 if (Parser.getTok().is(AsmToken::Hash)) {
2077 Parser.Lex(); // Eat hash.
2078 SMLoc ImmLoc = Parser.getTok().getLoc();
2079 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002080 if (getParser().ParseExpression(ShiftExpr)) {
2081 Error(ImmLoc, "invalid immediate shift value");
2082 return -1;
2083 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002084 // The expression must be evaluatable as an immediate.
2085 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002086 if (!CE) {
2087 Error(ImmLoc, "invalid immediate shift value");
2088 return -1;
2089 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002090 // Range check the immediate.
2091 // lsl, ror: 0 <= imm <= 31
2092 // lsr, asr: 0 <= imm <= 32
2093 Imm = CE->getValue();
2094 if (Imm < 0 ||
2095 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2096 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002097 Error(ImmLoc, "immediate shift value out of range");
2098 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002099 }
2100 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002101 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002102 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002103 if (ShiftReg == -1) {
2104 Error (L, "expected immediate or register in shift operand");
2105 return -1;
2106 }
2107 } else {
2108 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002109 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002110 return -1;
2111 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002112 }
2113
Owen Anderson92a20222011-07-21 18:54:16 +00002114 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2115 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002116 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002117 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002118 else
2119 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2120 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002121
Jim Grosbach19906722011-07-13 18:49:30 +00002122 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002123}
2124
2125
Bill Wendling50d0f582010-11-18 23:43:05 +00002126/// Try to parse a register name. The token must be an Identifier when called.
2127/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2128/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002129///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002130/// TODO this is likely to change to allow different register types and or to
2131/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002132bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002133tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002134 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002135 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002136 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002137 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002138
Bill Wendling50d0f582010-11-18 23:43:05 +00002139 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002140
Chris Lattnere5658fa2010-10-30 04:09:10 +00002141 const AsmToken &ExclaimTok = Parser.getTok();
2142 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002143 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2144 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002145 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002146 return false;
2147 }
2148
2149 // Also check for an index operand. This is only legal for vector registers,
2150 // but that'll get caught OK in operand matching, so we don't need to
2151 // explicitly filter everything else out here.
2152 if (Parser.getTok().is(AsmToken::LBrac)) {
2153 SMLoc SIdx = Parser.getTok().getLoc();
2154 Parser.Lex(); // Eat left bracket token.
2155
2156 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002157 if (getParser().ParseExpression(ImmVal))
2158 return MatchOperand_ParseFail;
2159 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2160 if (!MCE) {
2161 TokError("immediate value expected for vector index");
2162 return MatchOperand_ParseFail;
2163 }
2164
2165 SMLoc E = Parser.getTok().getLoc();
2166 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2167 Error(E, "']' expected");
2168 return MatchOperand_ParseFail;
2169 }
2170
2171 Parser.Lex(); // Eat right bracket token.
2172
2173 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2174 SIdx, E,
2175 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002176 }
2177
Bill Wendling50d0f582010-11-18 23:43:05 +00002178 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002179}
2180
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002181/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2182/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2183/// "c5", ...
2184static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002185 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2186 // but efficient.
2187 switch (Name.size()) {
2188 default: break;
2189 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002190 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002191 return -1;
2192 switch (Name[1]) {
2193 default: return -1;
2194 case '0': return 0;
2195 case '1': return 1;
2196 case '2': return 2;
2197 case '3': return 3;
2198 case '4': return 4;
2199 case '5': return 5;
2200 case '6': return 6;
2201 case '7': return 7;
2202 case '8': return 8;
2203 case '9': return 9;
2204 }
2205 break;
2206 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002207 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002208 return -1;
2209 switch (Name[2]) {
2210 default: return -1;
2211 case '0': return 10;
2212 case '1': return 11;
2213 case '2': return 12;
2214 case '3': return 13;
2215 case '4': return 14;
2216 case '5': return 15;
2217 }
2218 break;
2219 }
2220
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002221 return -1;
2222}
2223
Jim Grosbach89df9962011-08-26 21:43:41 +00002224/// parseITCondCode - Try to parse a condition code for an IT instruction.
2225ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2226parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2227 SMLoc S = Parser.getTok().getLoc();
2228 const AsmToken &Tok = Parser.getTok();
2229 if (!Tok.is(AsmToken::Identifier))
2230 return MatchOperand_NoMatch;
2231 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2232 .Case("eq", ARMCC::EQ)
2233 .Case("ne", ARMCC::NE)
2234 .Case("hs", ARMCC::HS)
2235 .Case("cs", ARMCC::HS)
2236 .Case("lo", ARMCC::LO)
2237 .Case("cc", ARMCC::LO)
2238 .Case("mi", ARMCC::MI)
2239 .Case("pl", ARMCC::PL)
2240 .Case("vs", ARMCC::VS)
2241 .Case("vc", ARMCC::VC)
2242 .Case("hi", ARMCC::HI)
2243 .Case("ls", ARMCC::LS)
2244 .Case("ge", ARMCC::GE)
2245 .Case("lt", ARMCC::LT)
2246 .Case("gt", ARMCC::GT)
2247 .Case("le", ARMCC::LE)
2248 .Case("al", ARMCC::AL)
2249 .Default(~0U);
2250 if (CC == ~0U)
2251 return MatchOperand_NoMatch;
2252 Parser.Lex(); // Eat the token.
2253
2254 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2255
2256 return MatchOperand_Success;
2257}
2258
Jim Grosbach43904292011-07-25 20:14:50 +00002259/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002260/// token must be an Identifier when called, and if it is a coprocessor
2261/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002262ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002263parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002264 SMLoc S = Parser.getTok().getLoc();
2265 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002266 if (Tok.isNot(AsmToken::Identifier))
2267 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002268
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002269 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002270 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002271 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002272
2273 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002274 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002275 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002276}
2277
Jim Grosbach43904292011-07-25 20:14:50 +00002278/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002279/// token must be an Identifier when called, and if it is a coprocessor
2280/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002281ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002282parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002283 SMLoc S = Parser.getTok().getLoc();
2284 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002285 if (Tok.isNot(AsmToken::Identifier))
2286 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002287
2288 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2289 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002290 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002291
2292 Parser.Lex(); // Eat identifier token.
2293 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002294 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002295}
2296
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002297/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2298/// coproc_option : '{' imm0_255 '}'
2299ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2300parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2301 SMLoc S = Parser.getTok().getLoc();
2302
2303 // If this isn't a '{', this isn't a coprocessor immediate operand.
2304 if (Parser.getTok().isNot(AsmToken::LCurly))
2305 return MatchOperand_NoMatch;
2306 Parser.Lex(); // Eat the '{'
2307
2308 const MCExpr *Expr;
2309 SMLoc Loc = Parser.getTok().getLoc();
2310 if (getParser().ParseExpression(Expr)) {
2311 Error(Loc, "illegal expression");
2312 return MatchOperand_ParseFail;
2313 }
2314 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2315 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2316 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2317 return MatchOperand_ParseFail;
2318 }
2319 int Val = CE->getValue();
2320
2321 // Check for and consume the closing '}'
2322 if (Parser.getTok().isNot(AsmToken::RCurly))
2323 return MatchOperand_ParseFail;
2324 SMLoc E = Parser.getTok().getLoc();
2325 Parser.Lex(); // Eat the '}'
2326
2327 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2328 return MatchOperand_Success;
2329}
2330
Jim Grosbachd0588e22011-09-14 18:08:35 +00002331// For register list parsing, we need to map from raw GPR register numbering
2332// to the enumeration values. The enumeration values aren't sorted by
2333// register number due to our using "sp", "lr" and "pc" as canonical names.
2334static unsigned getNextRegister(unsigned Reg) {
2335 // If this is a GPR, we need to do it manually, otherwise we can rely
2336 // on the sort ordering of the enumeration since the other reg-classes
2337 // are sane.
2338 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2339 return Reg + 1;
2340 switch(Reg) {
2341 default: assert(0 && "Invalid GPR number!");
2342 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2343 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2344 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2345 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2346 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2347 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2348 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2349 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2350 }
2351}
2352
2353/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002354bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002355parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002356 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002357 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002358 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002359 Parser.Lex(); // Eat '{' token.
2360 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002361
Jim Grosbachd0588e22011-09-14 18:08:35 +00002362 // Check the first register in the list to see what register class
2363 // this is a list of.
2364 int Reg = tryParseRegister();
2365 if (Reg == -1)
2366 return Error(RegLoc, "register expected");
2367
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002368 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002369 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2370 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2371 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2372 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2373 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2374 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2375 else
2376 return Error(RegLoc, "invalid register in register list");
2377
2378 // The reglist instructions have at most 16 registers, so reserve
2379 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002380 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002381 // Store the first register.
2382 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002383
Jim Grosbachd0588e22011-09-14 18:08:35 +00002384 // This starts immediately after the first register token in the list,
2385 // so we can see either a comma or a minus (range separator) as a legal
2386 // next token.
2387 while (Parser.getTok().is(AsmToken::Comma) ||
2388 Parser.getTok().is(AsmToken::Minus)) {
2389 if (Parser.getTok().is(AsmToken::Minus)) {
2390 Parser.Lex(); // Eat the comma.
2391 SMLoc EndLoc = Parser.getTok().getLoc();
2392 int EndReg = tryParseRegister();
2393 if (EndReg == -1)
2394 return Error(EndLoc, "register expected");
2395 // If the register is the same as the start reg, there's nothing
2396 // more to do.
2397 if (Reg == EndReg)
2398 continue;
2399 // The register must be in the same register class as the first.
2400 if (!RC->contains(EndReg))
2401 return Error(EndLoc, "invalid register in register list");
2402 // Ranges must go from low to high.
2403 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2404 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002405
Jim Grosbachd0588e22011-09-14 18:08:35 +00002406 // Add all the registers in the range to the register list.
2407 while (Reg != EndReg) {
2408 Reg = getNextRegister(Reg);
2409 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2410 }
2411 continue;
2412 }
2413 Parser.Lex(); // Eat the comma.
2414 RegLoc = Parser.getTok().getLoc();
2415 int OldReg = Reg;
2416 Reg = tryParseRegister();
2417 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002418 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002419 // The register must be in the same register class as the first.
2420 if (!RC->contains(Reg))
2421 return Error(RegLoc, "invalid register in register list");
2422 // List must be monotonically increasing.
2423 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2424 return Error(RegLoc, "register list not in ascending order");
2425 // VFP register lists must also be contiguous.
2426 // It's OK to use the enumeration values directly here rather, as the
2427 // VFP register classes have the enum sorted properly.
2428 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2429 Reg != OldReg + 1)
2430 return Error(RegLoc, "non-contiguous register range");
2431 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002432 }
2433
Jim Grosbachd0588e22011-09-14 18:08:35 +00002434 SMLoc E = Parser.getTok().getLoc();
2435 if (Parser.getTok().isNot(AsmToken::RCurly))
2436 return Error(E, "'}' expected");
2437 Parser.Lex(); // Eat '}' token.
2438
Bill Wendling50d0f582010-11-18 23:43:05 +00002439 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2440 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002441}
2442
Jim Grosbach862019c2011-10-18 23:02:30 +00002443// parse a vector register list
2444ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2445parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2446 if(Parser.getTok().isNot(AsmToken::LCurly))
2447 return MatchOperand_NoMatch;
2448
2449 SMLoc S = Parser.getTok().getLoc();
2450 Parser.Lex(); // Eat '{' token.
2451 SMLoc RegLoc = Parser.getTok().getLoc();
2452
2453 int Reg = tryParseRegister();
2454 if (Reg == -1) {
2455 Error(RegLoc, "register expected");
2456 return MatchOperand_ParseFail;
2457 }
2458
2459 unsigned FirstReg = Reg;
2460 unsigned Count = 1;
2461 while (Parser.getTok().is(AsmToken::Comma)) {
2462 Parser.Lex(); // Eat the comma.
2463 RegLoc = Parser.getTok().getLoc();
2464 int OldReg = Reg;
2465 Reg = tryParseRegister();
2466 if (Reg == -1) {
2467 Error(RegLoc, "register expected");
2468 return MatchOperand_ParseFail;
2469 }
2470 // vector register lists must also be contiguous.
2471 // It's OK to use the enumeration values directly here rather, as the
2472 // VFP register classes have the enum sorted properly.
2473 if (Reg != OldReg + 1) {
2474 Error(RegLoc, "non-contiguous register range");
2475 return MatchOperand_ParseFail;
2476 }
2477
2478 ++Count;
2479 }
2480
2481 SMLoc E = Parser.getTok().getLoc();
2482 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2483 Error(E, "'}' expected");
2484 return MatchOperand_ParseFail;
2485 }
2486 Parser.Lex(); // Eat '}' token.
2487
2488 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2489 return MatchOperand_Success;
2490}
2491
Jim Grosbach43904292011-07-25 20:14:50 +00002492/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002493ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002494parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002495 SMLoc S = Parser.getTok().getLoc();
2496 const AsmToken &Tok = Parser.getTok();
2497 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2498 StringRef OptStr = Tok.getString();
2499
2500 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2501 .Case("sy", ARM_MB::SY)
2502 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002503 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002504 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002505 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002506 .Case("ishst", ARM_MB::ISHST)
2507 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002508 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002509 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002510 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002511 .Case("osh", ARM_MB::OSH)
2512 .Case("oshst", ARM_MB::OSHST)
2513 .Default(~0U);
2514
2515 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002516 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002517
2518 Parser.Lex(); // Eat identifier token.
2519 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002520 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002521}
2522
Jim Grosbach43904292011-07-25 20:14:50 +00002523/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002524ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002525parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002526 SMLoc S = Parser.getTok().getLoc();
2527 const AsmToken &Tok = Parser.getTok();
2528 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2529 StringRef IFlagsStr = Tok.getString();
2530
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002531 // An iflags string of "none" is interpreted to mean that none of the AIF
2532 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002533 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002534 if (IFlagsStr != "none") {
2535 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2536 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2537 .Case("a", ARM_PROC::A)
2538 .Case("i", ARM_PROC::I)
2539 .Case("f", ARM_PROC::F)
2540 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002541
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002542 // If some specific iflag is already set, it means that some letter is
2543 // present more than once, this is not acceptable.
2544 if (Flag == ~0U || (IFlags & Flag))
2545 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002546
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002547 IFlags |= Flag;
2548 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002549 }
2550
2551 Parser.Lex(); // Eat identifier token.
2552 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2553 return MatchOperand_Success;
2554}
2555
Jim Grosbach43904292011-07-25 20:14:50 +00002556/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002557ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002558parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002559 SMLoc S = Parser.getTok().getLoc();
2560 const AsmToken &Tok = Parser.getTok();
2561 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2562 StringRef Mask = Tok.getString();
2563
James Molloyacad68d2011-09-28 14:21:38 +00002564 if (isMClass()) {
2565 // See ARMv6-M 10.1.1
2566 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2567 .Case("apsr", 0)
2568 .Case("iapsr", 1)
2569 .Case("eapsr", 2)
2570 .Case("xpsr", 3)
2571 .Case("ipsr", 5)
2572 .Case("epsr", 6)
2573 .Case("iepsr", 7)
2574 .Case("msp", 8)
2575 .Case("psp", 9)
2576 .Case("primask", 16)
2577 .Case("basepri", 17)
2578 .Case("basepri_max", 18)
2579 .Case("faultmask", 19)
2580 .Case("control", 20)
2581 .Default(~0U);
2582
2583 if (FlagsVal == ~0U)
2584 return MatchOperand_NoMatch;
2585
2586 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2587 // basepri, basepri_max and faultmask only valid for V7m.
2588 return MatchOperand_NoMatch;
2589
2590 Parser.Lex(); // Eat identifier token.
2591 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2592 return MatchOperand_Success;
2593 }
2594
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002595 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2596 size_t Start = 0, Next = Mask.find('_');
2597 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002598 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002599 if (Next != StringRef::npos)
2600 Flags = Mask.slice(Next+1, Mask.size());
2601
2602 // FlagsVal contains the complete mask:
2603 // 3-0: Mask
2604 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2605 unsigned FlagsVal = 0;
2606
2607 if (SpecReg == "apsr") {
2608 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002609 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002610 .Case("g", 0x4) // same as CPSR_s
2611 .Case("nzcvqg", 0xc) // same as CPSR_fs
2612 .Default(~0U);
2613
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002614 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002615 if (!Flags.empty())
2616 return MatchOperand_NoMatch;
2617 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002618 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002619 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002620 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002621 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2622 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002623 for (int i = 0, e = Flags.size(); i != e; ++i) {
2624 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2625 .Case("c", 1)
2626 .Case("x", 2)
2627 .Case("s", 4)
2628 .Case("f", 8)
2629 .Default(~0U);
2630
2631 // If some specific flag is already set, it means that some letter is
2632 // present more than once, this is not acceptable.
2633 if (FlagsVal == ~0U || (FlagsVal & Flag))
2634 return MatchOperand_NoMatch;
2635 FlagsVal |= Flag;
2636 }
2637 } else // No match for special register.
2638 return MatchOperand_NoMatch;
2639
Owen Anderson7784f1d2011-10-21 18:43:28 +00002640 // Special register without flags is NOT equivalent to "fc" flags.
2641 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2642 // two lines would enable gas compatibility at the expense of breaking
2643 // round-tripping.
2644 //
2645 // if (!FlagsVal)
2646 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002647
2648 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2649 if (SpecReg == "spsr")
2650 FlagsVal |= 16;
2651
2652 Parser.Lex(); // Eat identifier token.
2653 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2654 return MatchOperand_Success;
2655}
2656
Jim Grosbachf6c05252011-07-21 17:23:04 +00002657ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2658parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2659 int Low, int High) {
2660 const AsmToken &Tok = Parser.getTok();
2661 if (Tok.isNot(AsmToken::Identifier)) {
2662 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2663 return MatchOperand_ParseFail;
2664 }
2665 StringRef ShiftName = Tok.getString();
2666 std::string LowerOp = LowercaseString(Op);
2667 std::string UpperOp = UppercaseString(Op);
2668 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2669 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2670 return MatchOperand_ParseFail;
2671 }
2672 Parser.Lex(); // Eat shift type token.
2673
2674 // There must be a '#' and a shift amount.
2675 if (Parser.getTok().isNot(AsmToken::Hash)) {
2676 Error(Parser.getTok().getLoc(), "'#' expected");
2677 return MatchOperand_ParseFail;
2678 }
2679 Parser.Lex(); // Eat hash token.
2680
2681 const MCExpr *ShiftAmount;
2682 SMLoc Loc = Parser.getTok().getLoc();
2683 if (getParser().ParseExpression(ShiftAmount)) {
2684 Error(Loc, "illegal expression");
2685 return MatchOperand_ParseFail;
2686 }
2687 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2688 if (!CE) {
2689 Error(Loc, "constant expression expected");
2690 return MatchOperand_ParseFail;
2691 }
2692 int Val = CE->getValue();
2693 if (Val < Low || Val > High) {
2694 Error(Loc, "immediate value out of range");
2695 return MatchOperand_ParseFail;
2696 }
2697
2698 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2699
2700 return MatchOperand_Success;
2701}
2702
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002703ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2704parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2705 const AsmToken &Tok = Parser.getTok();
2706 SMLoc S = Tok.getLoc();
2707 if (Tok.isNot(AsmToken::Identifier)) {
2708 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2709 return MatchOperand_ParseFail;
2710 }
2711 int Val = StringSwitch<int>(Tok.getString())
2712 .Case("be", 1)
2713 .Case("le", 0)
2714 .Default(-1);
2715 Parser.Lex(); // Eat the token.
2716
2717 if (Val == -1) {
2718 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2719 return MatchOperand_ParseFail;
2720 }
2721 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2722 getContext()),
2723 S, Parser.getTok().getLoc()));
2724 return MatchOperand_Success;
2725}
2726
Jim Grosbach580f4a92011-07-25 22:20:28 +00002727/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2728/// instructions. Legal values are:
2729/// lsl #n 'n' in [0,31]
2730/// asr #n 'n' in [1,32]
2731/// n == 32 encoded as n == 0.
2732ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2733parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2734 const AsmToken &Tok = Parser.getTok();
2735 SMLoc S = Tok.getLoc();
2736 if (Tok.isNot(AsmToken::Identifier)) {
2737 Error(S, "shift operator 'asr' or 'lsl' expected");
2738 return MatchOperand_ParseFail;
2739 }
2740 StringRef ShiftName = Tok.getString();
2741 bool isASR;
2742 if (ShiftName == "lsl" || ShiftName == "LSL")
2743 isASR = false;
2744 else if (ShiftName == "asr" || ShiftName == "ASR")
2745 isASR = true;
2746 else {
2747 Error(S, "shift operator 'asr' or 'lsl' expected");
2748 return MatchOperand_ParseFail;
2749 }
2750 Parser.Lex(); // Eat the operator.
2751
2752 // A '#' and a shift amount.
2753 if (Parser.getTok().isNot(AsmToken::Hash)) {
2754 Error(Parser.getTok().getLoc(), "'#' expected");
2755 return MatchOperand_ParseFail;
2756 }
2757 Parser.Lex(); // Eat hash token.
2758
2759 const MCExpr *ShiftAmount;
2760 SMLoc E = Parser.getTok().getLoc();
2761 if (getParser().ParseExpression(ShiftAmount)) {
2762 Error(E, "malformed shift expression");
2763 return MatchOperand_ParseFail;
2764 }
2765 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2766 if (!CE) {
2767 Error(E, "shift amount must be an immediate");
2768 return MatchOperand_ParseFail;
2769 }
2770
2771 int64_t Val = CE->getValue();
2772 if (isASR) {
2773 // Shift amount must be in [1,32]
2774 if (Val < 1 || Val > 32) {
2775 Error(E, "'asr' shift amount must be in range [1,32]");
2776 return MatchOperand_ParseFail;
2777 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002778 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2779 if (isThumb() && Val == 32) {
2780 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2781 return MatchOperand_ParseFail;
2782 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002783 if (Val == 32) Val = 0;
2784 } else {
2785 // Shift amount must be in [1,32]
2786 if (Val < 0 || Val > 31) {
2787 Error(E, "'lsr' shift amount must be in range [0,31]");
2788 return MatchOperand_ParseFail;
2789 }
2790 }
2791
2792 E = Parser.getTok().getLoc();
2793 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2794
2795 return MatchOperand_Success;
2796}
2797
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002798/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2799/// of instructions. Legal values are:
2800/// ror #n 'n' in {0, 8, 16, 24}
2801ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2802parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2803 const AsmToken &Tok = Parser.getTok();
2804 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002805 if (Tok.isNot(AsmToken::Identifier))
2806 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002807 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002808 if (ShiftName != "ror" && ShiftName != "ROR")
2809 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002810 Parser.Lex(); // Eat the operator.
2811
2812 // A '#' and a rotate amount.
2813 if (Parser.getTok().isNot(AsmToken::Hash)) {
2814 Error(Parser.getTok().getLoc(), "'#' expected");
2815 return MatchOperand_ParseFail;
2816 }
2817 Parser.Lex(); // Eat hash token.
2818
2819 const MCExpr *ShiftAmount;
2820 SMLoc E = Parser.getTok().getLoc();
2821 if (getParser().ParseExpression(ShiftAmount)) {
2822 Error(E, "malformed rotate expression");
2823 return MatchOperand_ParseFail;
2824 }
2825 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2826 if (!CE) {
2827 Error(E, "rotate amount must be an immediate");
2828 return MatchOperand_ParseFail;
2829 }
2830
2831 int64_t Val = CE->getValue();
2832 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2833 // normally, zero is represented in asm by omitting the rotate operand
2834 // entirely.
2835 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2836 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2837 return MatchOperand_ParseFail;
2838 }
2839
2840 E = Parser.getTok().getLoc();
2841 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2842
2843 return MatchOperand_Success;
2844}
2845
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002846ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2847parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2848 SMLoc S = Parser.getTok().getLoc();
2849 // The bitfield descriptor is really two operands, the LSB and the width.
2850 if (Parser.getTok().isNot(AsmToken::Hash)) {
2851 Error(Parser.getTok().getLoc(), "'#' expected");
2852 return MatchOperand_ParseFail;
2853 }
2854 Parser.Lex(); // Eat hash token.
2855
2856 const MCExpr *LSBExpr;
2857 SMLoc E = Parser.getTok().getLoc();
2858 if (getParser().ParseExpression(LSBExpr)) {
2859 Error(E, "malformed immediate expression");
2860 return MatchOperand_ParseFail;
2861 }
2862 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2863 if (!CE) {
2864 Error(E, "'lsb' operand must be an immediate");
2865 return MatchOperand_ParseFail;
2866 }
2867
2868 int64_t LSB = CE->getValue();
2869 // The LSB must be in the range [0,31]
2870 if (LSB < 0 || LSB > 31) {
2871 Error(E, "'lsb' operand must be in the range [0,31]");
2872 return MatchOperand_ParseFail;
2873 }
2874 E = Parser.getTok().getLoc();
2875
2876 // Expect another immediate operand.
2877 if (Parser.getTok().isNot(AsmToken::Comma)) {
2878 Error(Parser.getTok().getLoc(), "too few operands");
2879 return MatchOperand_ParseFail;
2880 }
2881 Parser.Lex(); // Eat hash token.
2882 if (Parser.getTok().isNot(AsmToken::Hash)) {
2883 Error(Parser.getTok().getLoc(), "'#' expected");
2884 return MatchOperand_ParseFail;
2885 }
2886 Parser.Lex(); // Eat hash token.
2887
2888 const MCExpr *WidthExpr;
2889 if (getParser().ParseExpression(WidthExpr)) {
2890 Error(E, "malformed immediate expression");
2891 return MatchOperand_ParseFail;
2892 }
2893 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2894 if (!CE) {
2895 Error(E, "'width' operand must be an immediate");
2896 return MatchOperand_ParseFail;
2897 }
2898
2899 int64_t Width = CE->getValue();
2900 // The LSB must be in the range [1,32-lsb]
2901 if (Width < 1 || Width > 32 - LSB) {
2902 Error(E, "'width' operand must be in the range [1,32-lsb]");
2903 return MatchOperand_ParseFail;
2904 }
2905 E = Parser.getTok().getLoc();
2906
2907 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2908
2909 return MatchOperand_Success;
2910}
2911
Jim Grosbach7ce05792011-08-03 23:50:40 +00002912ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2913parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2914 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002915 // postidx_reg := '+' register {, shift}
2916 // | '-' register {, shift}
2917 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002918
2919 // This method must return MatchOperand_NoMatch without consuming any tokens
2920 // in the case where there is no match, as other alternatives take other
2921 // parse methods.
2922 AsmToken Tok = Parser.getTok();
2923 SMLoc S = Tok.getLoc();
2924 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002925 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002926 int Reg = -1;
2927 if (Tok.is(AsmToken::Plus)) {
2928 Parser.Lex(); // Eat the '+' token.
2929 haveEaten = true;
2930 } else if (Tok.is(AsmToken::Minus)) {
2931 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002932 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002933 haveEaten = true;
2934 }
2935 if (Parser.getTok().is(AsmToken::Identifier))
2936 Reg = tryParseRegister();
2937 if (Reg == -1) {
2938 if (!haveEaten)
2939 return MatchOperand_NoMatch;
2940 Error(Parser.getTok().getLoc(), "register expected");
2941 return MatchOperand_ParseFail;
2942 }
2943 SMLoc E = Parser.getTok().getLoc();
2944
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002945 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2946 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002947 if (Parser.getTok().is(AsmToken::Comma)) {
2948 Parser.Lex(); // Eat the ','.
2949 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2950 return MatchOperand_ParseFail;
2951 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002952
2953 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2954 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002955
2956 return MatchOperand_Success;
2957}
2958
Jim Grosbach251bf252011-08-10 21:56:18 +00002959ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2960parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2961 // Check for a post-index addressing register operand. Specifically:
2962 // am3offset := '+' register
2963 // | '-' register
2964 // | register
2965 // | # imm
2966 // | # + imm
2967 // | # - imm
2968
2969 // This method must return MatchOperand_NoMatch without consuming any tokens
2970 // in the case where there is no match, as other alternatives take other
2971 // parse methods.
2972 AsmToken Tok = Parser.getTok();
2973 SMLoc S = Tok.getLoc();
2974
2975 // Do immediates first, as we always parse those if we have a '#'.
2976 if (Parser.getTok().is(AsmToken::Hash)) {
2977 Parser.Lex(); // Eat the '#'.
2978 // Explicitly look for a '-', as we need to encode negative zero
2979 // differently.
2980 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2981 const MCExpr *Offset;
2982 if (getParser().ParseExpression(Offset))
2983 return MatchOperand_ParseFail;
2984 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2985 if (!CE) {
2986 Error(S, "constant expression expected");
2987 return MatchOperand_ParseFail;
2988 }
2989 SMLoc E = Tok.getLoc();
2990 // Negative zero is encoded as the flag value INT32_MIN.
2991 int32_t Val = CE->getValue();
2992 if (isNegative && Val == 0)
2993 Val = INT32_MIN;
2994
2995 Operands.push_back(
2996 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2997
2998 return MatchOperand_Success;
2999 }
3000
3001
3002 bool haveEaten = false;
3003 bool isAdd = true;
3004 int Reg = -1;
3005 if (Tok.is(AsmToken::Plus)) {
3006 Parser.Lex(); // Eat the '+' token.
3007 haveEaten = true;
3008 } else if (Tok.is(AsmToken::Minus)) {
3009 Parser.Lex(); // Eat the '-' token.
3010 isAdd = false;
3011 haveEaten = true;
3012 }
3013 if (Parser.getTok().is(AsmToken::Identifier))
3014 Reg = tryParseRegister();
3015 if (Reg == -1) {
3016 if (!haveEaten)
3017 return MatchOperand_NoMatch;
3018 Error(Parser.getTok().getLoc(), "register expected");
3019 return MatchOperand_ParseFail;
3020 }
3021 SMLoc E = Parser.getTok().getLoc();
3022
3023 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3024 0, S, E));
3025
3026 return MatchOperand_Success;
3027}
3028
Jim Grosbacha77295d2011-09-08 22:07:06 +00003029/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3030/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3031/// when they refer multiple MIOperands inside a single one.
3032bool ARMAsmParser::
3033cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3034 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3035 // Rt, Rt2
3036 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3037 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3038 // Create a writeback register dummy placeholder.
3039 Inst.addOperand(MCOperand::CreateReg(0));
3040 // addr
3041 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3042 // pred
3043 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3044 return true;
3045}
3046
3047/// cvtT2StrdPre - Convert parsed operands to MCInst.
3048/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3049/// when they refer multiple MIOperands inside a single one.
3050bool ARMAsmParser::
3051cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3052 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3053 // Create a writeback register dummy placeholder.
3054 Inst.addOperand(MCOperand::CreateReg(0));
3055 // Rt, Rt2
3056 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3057 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3058 // addr
3059 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3060 // pred
3061 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3062 return true;
3063}
3064
Jim Grosbacheeec0252011-09-08 00:39:19 +00003065/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3066/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3067/// when they refer multiple MIOperands inside a single one.
3068bool ARMAsmParser::
3069cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3070 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3071 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3072
3073 // Create a writeback register dummy placeholder.
3074 Inst.addOperand(MCOperand::CreateImm(0));
3075
3076 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3077 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3078 return true;
3079}
3080
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003081/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3082/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3083/// when they refer multiple MIOperands inside a single one.
3084bool ARMAsmParser::
3085cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3086 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3087 // Create a writeback register dummy placeholder.
3088 Inst.addOperand(MCOperand::CreateImm(0));
3089 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3090 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3091 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3092 return true;
3093}
3094
Jim Grosbach1355cf12011-07-26 17:10:22 +00003095/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003096/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3097/// when they refer multiple MIOperands inside a single one.
3098bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003099cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003100 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3101 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3102
3103 // Create a writeback register dummy placeholder.
3104 Inst.addOperand(MCOperand::CreateImm(0));
3105
Jim Grosbach7ce05792011-08-03 23:50:40 +00003106 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003107 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3108 return true;
3109}
3110
Owen Anderson9ab0f252011-08-26 20:43:14 +00003111/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3112/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3113/// when they refer multiple MIOperands inside a single one.
3114bool ARMAsmParser::
3115cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3116 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3117 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3118
3119 // Create a writeback register dummy placeholder.
3120 Inst.addOperand(MCOperand::CreateImm(0));
3121
3122 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3123 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3124 return true;
3125}
3126
3127
Jim Grosbach548340c2011-08-11 19:22:40 +00003128/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3129/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3130/// when they refer multiple MIOperands inside a single one.
3131bool ARMAsmParser::
3132cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3133 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3134 // Create a writeback register dummy placeholder.
3135 Inst.addOperand(MCOperand::CreateImm(0));
3136 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3137 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3138 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3139 return true;
3140}
3141
Jim Grosbach1355cf12011-07-26 17:10:22 +00003142/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003143/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3144/// when they refer multiple MIOperands inside a single one.
3145bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003146cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003147 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3148 // Create a writeback register dummy placeholder.
3149 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003150 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3151 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3152 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003153 return true;
3154}
3155
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003156/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3157/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3158/// when they refer multiple MIOperands inside a single one.
3159bool ARMAsmParser::
3160cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3161 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3162 // Create a writeback register dummy placeholder.
3163 Inst.addOperand(MCOperand::CreateImm(0));
3164 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3165 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3166 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3167 return true;
3168}
3169
Jim Grosbach7ce05792011-08-03 23:50:40 +00003170/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3171/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3172/// when they refer multiple MIOperands inside a single one.
3173bool ARMAsmParser::
3174cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3175 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3176 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003177 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003178 // Create a writeback register dummy placeholder.
3179 Inst.addOperand(MCOperand::CreateImm(0));
3180 // addr
3181 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3182 // offset
3183 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3184 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003185 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3186 return true;
3187}
3188
Jim Grosbach7ce05792011-08-03 23:50:40 +00003189/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003190/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3191/// when they refer multiple MIOperands inside a single one.
3192bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003193cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3194 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3195 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003196 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003197 // Create a writeback register dummy placeholder.
3198 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003199 // addr
3200 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3201 // offset
3202 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3203 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003204 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3205 return true;
3206}
3207
Jim Grosbach7ce05792011-08-03 23:50:40 +00003208/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003209/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3210/// when they refer multiple MIOperands inside a single one.
3211bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003212cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3213 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003214 // Create a writeback register dummy placeholder.
3215 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003216 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003217 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003218 // addr
3219 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3220 // offset
3221 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3222 // pred
3223 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3224 return true;
3225}
3226
3227/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3228/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3229/// when they refer multiple MIOperands inside a single one.
3230bool ARMAsmParser::
3231cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3232 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3233 // Create a writeback register dummy placeholder.
3234 Inst.addOperand(MCOperand::CreateImm(0));
3235 // Rt
3236 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3237 // addr
3238 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3239 // offset
3240 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3241 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003242 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3243 return true;
3244}
3245
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003246/// cvtLdrdPre - Convert parsed operands to MCInst.
3247/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3248/// when they refer multiple MIOperands inside a single one.
3249bool ARMAsmParser::
3250cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3251 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3252 // Rt, Rt2
3253 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3254 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3255 // Create a writeback register dummy placeholder.
3256 Inst.addOperand(MCOperand::CreateImm(0));
3257 // addr
3258 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3259 // pred
3260 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3261 return true;
3262}
3263
Jim Grosbach14605d12011-08-11 20:28:23 +00003264/// cvtStrdPre - Convert parsed operands to MCInst.
3265/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3266/// when they refer multiple MIOperands inside a single one.
3267bool ARMAsmParser::
3268cvtStrdPre(MCInst &Inst, unsigned Opcode,
3269 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3270 // Create a writeback register dummy placeholder.
3271 Inst.addOperand(MCOperand::CreateImm(0));
3272 // Rt, Rt2
3273 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3274 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3275 // addr
3276 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3277 // pred
3278 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3279 return true;
3280}
3281
Jim Grosbach623a4542011-08-10 22:42:16 +00003282/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3283/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3284/// when they refer multiple MIOperands inside a single one.
3285bool ARMAsmParser::
3286cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3287 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3288 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3289 // Create a writeback register dummy placeholder.
3290 Inst.addOperand(MCOperand::CreateImm(0));
3291 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3292 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3293 return true;
3294}
3295
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003296/// cvtThumbMultiple- Convert parsed operands to MCInst.
3297/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3298/// when they refer multiple MIOperands inside a single one.
3299bool ARMAsmParser::
3300cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3301 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3302 // The second source operand must be the same register as the destination
3303 // operand.
3304 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003305 (((ARMOperand*)Operands[3])->getReg() !=
3306 ((ARMOperand*)Operands[5])->getReg()) &&
3307 (((ARMOperand*)Operands[3])->getReg() !=
3308 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003309 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003310 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003311 return false;
3312 }
3313 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3314 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3315 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003316 // If we have a three-operand form, use that, else the second source operand
3317 // is just the destination operand again.
3318 if (Operands.size() == 6)
3319 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3320 else
3321 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003322 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3323
3324 return true;
3325}
Jim Grosbach623a4542011-08-10 22:42:16 +00003326
Jim Grosbach12431322011-10-24 22:16:58 +00003327bool ARMAsmParser::
3328cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3329 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3330 // Vd
3331 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3332 // Create a writeback register dummy placeholder.
3333 Inst.addOperand(MCOperand::CreateImm(0));
3334 // Vn
3335 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3336 // pred
3337 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3338 return true;
3339}
3340
3341bool ARMAsmParser::
3342cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3343 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3344 // Vd
3345 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3346 // Create a writeback register dummy placeholder.
3347 Inst.addOperand(MCOperand::CreateImm(0));
3348 // Vn
3349 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3350 // Vm
3351 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3352 // pred
3353 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3354 return true;
3355}
3356
Bill Wendlinge7176102010-11-06 22:36:58 +00003357/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003358/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003359bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003360parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003361 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003362 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003363 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003364 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003365 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003366
Sean Callanan18b83232010-01-19 21:44:56 +00003367 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003368 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003369 if (BaseRegNum == -1)
3370 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003371
Daniel Dunbar05710932011-01-18 05:34:17 +00003372 // The next token must either be a comma or a closing bracket.
3373 const AsmToken &Tok = Parser.getTok();
3374 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003375 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003376
Jim Grosbach7ce05792011-08-03 23:50:40 +00003377 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003378 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003379 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003380
Jim Grosbach7ce05792011-08-03 23:50:40 +00003381 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003382 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003383
Jim Grosbachfb12f352011-09-19 18:42:21 +00003384 // If there's a pre-indexing writeback marker, '!', just add it as a token
3385 // operand. It's rather odd, but syntactically valid.
3386 if (Parser.getTok().is(AsmToken::Exclaim)) {
3387 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3388 Parser.Lex(); // Eat the '!'.
3389 }
3390
Jim Grosbach7ce05792011-08-03 23:50:40 +00003391 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003392 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003393
Jim Grosbach7ce05792011-08-03 23:50:40 +00003394 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3395 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003396
Jim Grosbach57dcb852011-10-11 17:29:55 +00003397 // If we have a ':', it's an alignment specifier.
3398 if (Parser.getTok().is(AsmToken::Colon)) {
3399 Parser.Lex(); // Eat the ':'.
3400 E = Parser.getTok().getLoc();
3401
3402 const MCExpr *Expr;
3403 if (getParser().ParseExpression(Expr))
3404 return true;
3405
3406 // The expression has to be a constant. Memory references with relocations
3407 // don't come through here, as they use the <label> forms of the relevant
3408 // instructions.
3409 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3410 if (!CE)
3411 return Error (E, "constant expression expected");
3412
3413 unsigned Align = 0;
3414 switch (CE->getValue()) {
3415 default:
3416 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3417 case 64: Align = 8; break;
3418 case 128: Align = 16; break;
3419 case 256: Align = 32; break;
3420 }
3421
3422 // Now we should have the closing ']'
3423 E = Parser.getTok().getLoc();
3424 if (Parser.getTok().isNot(AsmToken::RBrac))
3425 return Error(E, "']' expected");
3426 Parser.Lex(); // Eat right bracket token.
3427
3428 // Don't worry about range checking the value here. That's handled by
3429 // the is*() predicates.
3430 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3431 ARM_AM::no_shift, 0, Align,
3432 false, S, E));
3433
3434 // If there's a pre-indexing writeback marker, '!', just add it as a token
3435 // operand.
3436 if (Parser.getTok().is(AsmToken::Exclaim)) {
3437 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3438 Parser.Lex(); // Eat the '!'.
3439 }
3440
3441 return false;
3442 }
3443
3444 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003445 // offset.
3446 if (Parser.getTok().is(AsmToken::Hash)) {
3447 Parser.Lex(); // Eat the '#'.
3448 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003449
Owen Anderson0da10cf2011-08-29 19:36:44 +00003450 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003451 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003452 if (getParser().ParseExpression(Offset))
3453 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003454
3455 // The expression has to be a constant. Memory references with relocations
3456 // don't come through here, as they use the <label> forms of the relevant
3457 // instructions.
3458 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3459 if (!CE)
3460 return Error (E, "constant expression expected");
3461
Owen Anderson0da10cf2011-08-29 19:36:44 +00003462 // If the constant was #-0, represent it as INT32_MIN.
3463 int32_t Val = CE->getValue();
3464 if (isNegative && Val == 0)
3465 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3466
Jim Grosbach7ce05792011-08-03 23:50:40 +00003467 // Now we should have the closing ']'
3468 E = Parser.getTok().getLoc();
3469 if (Parser.getTok().isNot(AsmToken::RBrac))
3470 return Error(E, "']' expected");
3471 Parser.Lex(); // Eat right bracket token.
3472
3473 // Don't worry about range checking the value here. That's handled by
3474 // the is*() predicates.
3475 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003476 ARM_AM::no_shift, 0, 0,
3477 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003478
3479 // If there's a pre-indexing writeback marker, '!', just add it as a token
3480 // operand.
3481 if (Parser.getTok().is(AsmToken::Exclaim)) {
3482 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3483 Parser.Lex(); // Eat the '!'.
3484 }
3485
3486 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003487 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003488
3489 // The register offset is optionally preceded by a '+' or '-'
3490 bool isNegative = false;
3491 if (Parser.getTok().is(AsmToken::Minus)) {
3492 isNegative = true;
3493 Parser.Lex(); // Eat the '-'.
3494 } else if (Parser.getTok().is(AsmToken::Plus)) {
3495 // Nothing to do.
3496 Parser.Lex(); // Eat the '+'.
3497 }
3498
3499 E = Parser.getTok().getLoc();
3500 int OffsetRegNum = tryParseRegister();
3501 if (OffsetRegNum == -1)
3502 return Error(E, "register expected");
3503
3504 // If there's a shift operator, handle it.
3505 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003506 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003507 if (Parser.getTok().is(AsmToken::Comma)) {
3508 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003509 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003510 return true;
3511 }
3512
3513 // Now we should have the closing ']'
3514 E = Parser.getTok().getLoc();
3515 if (Parser.getTok().isNot(AsmToken::RBrac))
3516 return Error(E, "']' expected");
3517 Parser.Lex(); // Eat right bracket token.
3518
3519 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003520 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003521 S, E));
3522
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003523 // If there's a pre-indexing writeback marker, '!', just add it as a token
3524 // operand.
3525 if (Parser.getTok().is(AsmToken::Exclaim)) {
3526 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3527 Parser.Lex(); // Eat the '!'.
3528 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003529
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003530 return false;
3531}
3532
Jim Grosbach7ce05792011-08-03 23:50:40 +00003533/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003534/// ( lsl | lsr | asr | ror ) , # shift_amount
3535/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003536/// return true if it parses a shift otherwise it returns false.
3537bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3538 unsigned &Amount) {
3539 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003540 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003541 if (Tok.isNot(AsmToken::Identifier))
3542 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003543 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003544 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003545 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003546 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003547 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003548 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003549 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003550 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003551 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003552 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003553 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003554 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003555 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003556 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003557
Jim Grosbach7ce05792011-08-03 23:50:40 +00003558 // rrx stands alone.
3559 Amount = 0;
3560 if (St != ARM_AM::rrx) {
3561 Loc = Parser.getTok().getLoc();
3562 // A '#' and a shift amount.
3563 const AsmToken &HashTok = Parser.getTok();
3564 if (HashTok.isNot(AsmToken::Hash))
3565 return Error(HashTok.getLoc(), "'#' expected");
3566 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003567
Jim Grosbach7ce05792011-08-03 23:50:40 +00003568 const MCExpr *Expr;
3569 if (getParser().ParseExpression(Expr))
3570 return true;
3571 // Range check the immediate.
3572 // lsl, ror: 0 <= imm <= 31
3573 // lsr, asr: 0 <= imm <= 32
3574 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3575 if (!CE)
3576 return Error(Loc, "shift amount must be an immediate");
3577 int64_t Imm = CE->getValue();
3578 if (Imm < 0 ||
3579 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3580 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3581 return Error(Loc, "immediate shift value out of range");
3582 Amount = Imm;
3583 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003584
3585 return false;
3586}
3587
Jim Grosbach9d390362011-10-03 23:38:36 +00003588/// parseFPImm - A floating point immediate expression operand.
3589ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3590parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3591 SMLoc S = Parser.getTok().getLoc();
3592
3593 if (Parser.getTok().isNot(AsmToken::Hash))
3594 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003595
3596 // Disambiguate the VMOV forms that can accept an FP immediate.
3597 // vmov.f32 <sreg>, #imm
3598 // vmov.f64 <dreg>, #imm
3599 // vmov.f32 <dreg>, #imm @ vector f32x2
3600 // vmov.f32 <qreg>, #imm @ vector f32x4
3601 //
3602 // There are also the NEON VMOV instructions which expect an
3603 // integer constant. Make sure we don't try to parse an FPImm
3604 // for these:
3605 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3606 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3607 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3608 TyOp->getToken() != ".f64"))
3609 return MatchOperand_NoMatch;
3610
Jim Grosbach9d390362011-10-03 23:38:36 +00003611 Parser.Lex(); // Eat the '#'.
3612
3613 // Handle negation, as that still comes through as a separate token.
3614 bool isNegative = false;
3615 if (Parser.getTok().is(AsmToken::Minus)) {
3616 isNegative = true;
3617 Parser.Lex();
3618 }
3619 const AsmToken &Tok = Parser.getTok();
3620 if (Tok.is(AsmToken::Real)) {
3621 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3622 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3623 // If we had a '-' in front, toggle the sign bit.
3624 IntVal ^= (uint64_t)isNegative << 63;
3625 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3626 Parser.Lex(); // Eat the token.
3627 if (Val == -1) {
3628 TokError("floating point value out of range");
3629 return MatchOperand_ParseFail;
3630 }
3631 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3632 return MatchOperand_Success;
3633 }
3634 if (Tok.is(AsmToken::Integer)) {
3635 int64_t Val = Tok.getIntVal();
3636 Parser.Lex(); // Eat the token.
3637 if (Val > 255 || Val < 0) {
3638 TokError("encoded floating point value out of range");
3639 return MatchOperand_ParseFail;
3640 }
3641 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3642 return MatchOperand_Success;
3643 }
3644
3645 TokError("invalid floating point immediate");
3646 return MatchOperand_ParseFail;
3647}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003648/// Parse a arm instruction operand. For now this parses the operand regardless
3649/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003650bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003651 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003652 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003653
3654 // Check if the current operand has a custom associated parser, if so, try to
3655 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003656 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3657 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003658 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003659 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3660 // there was a match, but an error occurred, in which case, just return that
3661 // the operand parsing failed.
3662 if (ResTy == MatchOperand_ParseFail)
3663 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003664
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003665 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003666 default:
3667 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003668 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003669 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003670 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003671 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003672 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003673 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003674 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003675 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003676 else if (Res == -1) // irrecoverable error
3677 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003678 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3679 S = Parser.getTok().getLoc();
3680 Parser.Lex();
3681 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3682 return false;
3683 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003684
3685 // Fall though for the Identifier case that is not a register or a
3686 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003687 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003688 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003689 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3690 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003691 // This was not a register so parse other operands that start with an
3692 // identifier (like labels) as expressions and create them as immediates.
3693 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003694 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003695 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003696 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003697 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003698 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3699 return false;
3700 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003701 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003702 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003703 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003704 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003705 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003706 // #42 -> immediate.
3707 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003708 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003709 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003710 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003711 const MCExpr *ImmVal;
3712 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003713 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003714 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3715 if (!CE) {
3716 Error(S, "constant expression expected");
3717 return MatchOperand_ParseFail;
3718 }
3719 int32_t Val = CE->getValue();
3720 if (isNegative && Val == 0)
3721 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003722 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003723 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3724 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003725 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003726 case AsmToken::Colon: {
3727 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003728 // FIXME: Check it's an expression prefix,
3729 // e.g. (FOO - :lower16:BAR) isn't legal.
3730 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003731 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003732 return true;
3733
Evan Cheng75972122011-01-13 07:58:56 +00003734 const MCExpr *SubExprVal;
3735 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003736 return true;
3737
Evan Cheng75972122011-01-13 07:58:56 +00003738 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3739 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003740 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003741 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003742 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003743 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003744 }
3745}
3746
Jim Grosbach1355cf12011-07-26 17:10:22 +00003747// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003748// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003749bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003750 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003751
3752 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003753 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003754 Parser.Lex(); // Eat ':'
3755
3756 if (getLexer().isNot(AsmToken::Identifier)) {
3757 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3758 return true;
3759 }
3760
3761 StringRef IDVal = Parser.getTok().getIdentifier();
3762 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003763 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003764 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003765 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003766 } else {
3767 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3768 return true;
3769 }
3770 Parser.Lex();
3771
3772 if (getLexer().isNot(AsmToken::Colon)) {
3773 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3774 return true;
3775 }
3776 Parser.Lex(); // Eat the last ':'
3777 return false;
3778}
3779
Daniel Dunbar352e1482011-01-11 15:59:50 +00003780/// \brief Given a mnemonic, split out possible predication code and carry
3781/// setting letters to form a canonical mnemonic and flags.
3782//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003783// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003784// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003785StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003786 unsigned &PredicationCode,
3787 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003788 unsigned &ProcessorIMod,
3789 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003790 PredicationCode = ARMCC::AL;
3791 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003792 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003793
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003794 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003795 //
3796 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003797 if ((Mnemonic == "movs" && isThumb()) ||
3798 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3799 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3800 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3801 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3802 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3803 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3804 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003805 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003806
Jim Grosbach3f00e312011-07-11 17:09:57 +00003807 // First, split out any predication code. Ignore mnemonics we know aren't
3808 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003809 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003810 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003811 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003812 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003813 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3814 .Case("eq", ARMCC::EQ)
3815 .Case("ne", ARMCC::NE)
3816 .Case("hs", ARMCC::HS)
3817 .Case("cs", ARMCC::HS)
3818 .Case("lo", ARMCC::LO)
3819 .Case("cc", ARMCC::LO)
3820 .Case("mi", ARMCC::MI)
3821 .Case("pl", ARMCC::PL)
3822 .Case("vs", ARMCC::VS)
3823 .Case("vc", ARMCC::VC)
3824 .Case("hi", ARMCC::HI)
3825 .Case("ls", ARMCC::LS)
3826 .Case("ge", ARMCC::GE)
3827 .Case("lt", ARMCC::LT)
3828 .Case("gt", ARMCC::GT)
3829 .Case("le", ARMCC::LE)
3830 .Case("al", ARMCC::AL)
3831 .Default(~0U);
3832 if (CC != ~0U) {
3833 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3834 PredicationCode = CC;
3835 }
Bill Wendling52925b62010-10-29 23:50:21 +00003836 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003837
Daniel Dunbar352e1482011-01-11 15:59:50 +00003838 // Next, determine if we have a carry setting bit. We explicitly ignore all
3839 // the instructions we know end in 's'.
3840 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003841 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003842 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3843 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3844 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003845 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3846 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003847 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3848 CarrySetting = true;
3849 }
3850
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003851 // The "cps" instruction can have a interrupt mode operand which is glued into
3852 // the mnemonic. Check if this is the case, split it and parse the imod op
3853 if (Mnemonic.startswith("cps")) {
3854 // Split out any imod code.
3855 unsigned IMod =
3856 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3857 .Case("ie", ARM_PROC::IE)
3858 .Case("id", ARM_PROC::ID)
3859 .Default(~0U);
3860 if (IMod != ~0U) {
3861 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3862 ProcessorIMod = IMod;
3863 }
3864 }
3865
Jim Grosbach89df9962011-08-26 21:43:41 +00003866 // The "it" instruction has the condition mask on the end of the mnemonic.
3867 if (Mnemonic.startswith("it")) {
3868 ITMask = Mnemonic.slice(2, Mnemonic.size());
3869 Mnemonic = Mnemonic.slice(0, 2);
3870 }
3871
Daniel Dunbar352e1482011-01-11 15:59:50 +00003872 return Mnemonic;
3873}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003874
3875/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3876/// inclusion of carry set or predication code operands.
3877//
3878// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003879void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003880getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003881 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003882 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3883 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003884 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003885 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003886 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003887 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003888 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003889 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003890 Mnemonic == "mla" || Mnemonic == "smlal" ||
3891 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003892 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003893 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003894 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003895
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003896 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3897 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3898 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3899 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003900 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3901 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003902 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003903 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3904 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3905 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003906 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3907 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003908 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003909 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003910 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003911 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003912
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003913 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003914 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003915 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003916 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003917 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003918}
3919
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003920bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3921 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003922 // FIXME: This is all horribly hacky. We really need a better way to deal
3923 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003924
3925 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3926 // another does not. Specifically, the MOVW instruction does not. So we
3927 // special case it here and remove the defaulted (non-setting) cc_out
3928 // operand if that's the instruction we're trying to match.
3929 //
3930 // We do this as post-processing of the explicit operands rather than just
3931 // conditionally adding the cc_out in the first place because we need
3932 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003933 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003934 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3935 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3936 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3937 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003938
3939 // Register-register 'add' for thumb does not have a cc_out operand
3940 // when there are only two register operands.
3941 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3942 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3943 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3944 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3945 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003946 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003947 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3948 // have to check the immediate range here since Thumb2 has a variant
3949 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003950 if (((isThumb() && Mnemonic == "add") ||
3951 (isThumbTwo() && Mnemonic == "sub")) &&
3952 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003953 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3954 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3955 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003956 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3957 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3958 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003959 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003960 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3961 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003962 // selecting via the generic "add" mnemonic, so to know that we
3963 // should remove the cc_out operand, we have to explicitly check that
3964 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003965 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3966 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003967 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3968 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3969 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3970 // Nest conditions rather than one big 'if' statement for readability.
3971 //
3972 // If either register is a high reg, it's either one of the SP
3973 // variants (handled above) or a 32-bit encoding, so we just
3974 // check against T3.
3975 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3976 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3977 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3978 return false;
3979 // If both registers are low, we're in an IT block, and the immediate is
3980 // in range, we should use encoding T1 instead, which has a cc_out.
3981 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003982 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003983 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3984 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3985 return false;
3986
3987 // Otherwise, we use encoding T4, which does not have a cc_out
3988 // operand.
3989 return true;
3990 }
3991
Jim Grosbach64944f42011-09-14 21:00:40 +00003992 // The thumb2 multiply instruction doesn't have a CCOut register, so
3993 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3994 // use the 16-bit encoding or not.
3995 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3996 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3997 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3998 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3999 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4000 // If the registers aren't low regs, the destination reg isn't the
4001 // same as one of the source regs, or the cc_out operand is zero
4002 // outside of an IT block, we have to use the 32-bit encoding, so
4003 // remove the cc_out operand.
4004 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4005 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4006 !inITBlock() ||
4007 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4008 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4009 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4010 static_cast<ARMOperand*>(Operands[4])->getReg())))
4011 return true;
4012
4013
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004014
Jim Grosbachf69c8042011-08-24 21:42:27 +00004015 // Register-register 'add/sub' for thumb does not have a cc_out operand
4016 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4017 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4018 // right, this will result in better diagnostics (which operand is off)
4019 // anyway.
4020 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4021 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004022 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4023 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4024 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4025 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004026
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004027 return false;
4028}
4029
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004030/// Parse an arm instruction mnemonic followed by its operands.
4031bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4032 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4033 // Create the leading tokens for the mnemonic, split by '.' characters.
4034 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004035 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004036
Daniel Dunbar352e1482011-01-11 15:59:50 +00004037 // Split out the predication code and carry setting flag from the mnemonic.
4038 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004039 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004040 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004041 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004042 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004043 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004044
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004045 // In Thumb1, only the branch (B) instruction can be predicated.
4046 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4047 Parser.EatToEndOfStatement();
4048 return Error(NameLoc, "conditional execution not supported in Thumb1");
4049 }
4050
Jim Grosbachffa32252011-07-19 19:13:28 +00004051 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4052
Jim Grosbach89df9962011-08-26 21:43:41 +00004053 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4054 // is the mask as it will be for the IT encoding if the conditional
4055 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4056 // where the conditional bit0 is zero, the instruction post-processing
4057 // will adjust the mask accordingly.
4058 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004059 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4060 if (ITMask.size() > 3) {
4061 Parser.EatToEndOfStatement();
4062 return Error(Loc, "too many conditions on IT instruction");
4063 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004064 unsigned Mask = 8;
4065 for (unsigned i = ITMask.size(); i != 0; --i) {
4066 char pos = ITMask[i - 1];
4067 if (pos != 't' && pos != 'e') {
4068 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004069 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004070 }
4071 Mask >>= 1;
4072 if (ITMask[i - 1] == 't')
4073 Mask |= 8;
4074 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004075 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004076 }
4077
Jim Grosbachffa32252011-07-19 19:13:28 +00004078 // FIXME: This is all a pretty gross hack. We should automatically handle
4079 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004080
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004081 // Next, add the CCOut and ConditionCode operands, if needed.
4082 //
4083 // For mnemonics which can ever incorporate a carry setting bit or predication
4084 // code, our matching model involves us always generating CCOut and
4085 // ConditionCode operands to match the mnemonic "as written" and then we let
4086 // the matcher deal with finding the right instruction or generating an
4087 // appropriate error.
4088 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004089 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004090
Jim Grosbach33c16a22011-07-14 22:04:21 +00004091 // If we had a carry-set on an instruction that can't do that, issue an
4092 // error.
4093 if (!CanAcceptCarrySet && CarrySetting) {
4094 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004095 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004096 "' can not set flags, but 's' suffix specified");
4097 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004098 // If we had a predication code on an instruction that can't do that, issue an
4099 // error.
4100 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4101 Parser.EatToEndOfStatement();
4102 return Error(NameLoc, "instruction '" + Mnemonic +
4103 "' is not predicable, but condition code specified");
4104 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004105
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004106 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004107 if (CanAcceptCarrySet) {
4108 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004109 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004110 Loc));
4111 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004112
4113 // Add the predication code operand, if necessary.
4114 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004115 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4116 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004117 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004118 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004119 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004120
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004121 // Add the processor imod operand, if necessary.
4122 if (ProcessorIMod) {
4123 Operands.push_back(ARMOperand::CreateImm(
4124 MCConstantExpr::Create(ProcessorIMod, getContext()),
4125 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004126 }
4127
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004128 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004129 while (Next != StringRef::npos) {
4130 Start = Next;
4131 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004132 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004133
Jim Grosbach4d23e992011-08-24 22:19:48 +00004134 // For now, we're only parsing Thumb1 (for the most part), so
4135 // just ignore ".n" qualifiers. We'll use them to restrict
4136 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00004137 if (ExtraToken != ".n") {
4138 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4139 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4140 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004141 }
4142
4143 // Read the remaining operands.
4144 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004145 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004146 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004147 Parser.EatToEndOfStatement();
4148 return true;
4149 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004150
4151 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004152 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004153
4154 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004155 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004156 Parser.EatToEndOfStatement();
4157 return true;
4158 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004159 }
4160 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004161
Chris Lattnercbf8a982010-09-11 16:18:25 +00004162 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004163 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004164 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004165 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004166 }
Bill Wendling146018f2010-11-06 21:42:12 +00004167
Chris Lattner34e53142010-09-08 05:10:46 +00004168 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004169
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004170 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4171 // do and don't have a cc_out optional-def operand. With some spot-checks
4172 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004173 // parse and adjust accordingly before actually matching. We shouldn't ever
4174 // try to remove a cc_out operand that was explicitly set on the the
4175 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4176 // table driven matcher doesn't fit well with the ARM instruction set.
4177 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004178 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4179 Operands.erase(Operands.begin() + 1);
4180 delete Op;
4181 }
4182
Jim Grosbachcf121c32011-07-28 21:57:55 +00004183 // ARM mode 'blx' need special handling, as the register operand version
4184 // is predicable, but the label operand version is not. So, we can't rely
4185 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004186 // a k_CondCode operand in the list. If we're trying to match the label
4187 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004188 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4189 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4190 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4191 Operands.erase(Operands.begin() + 1);
4192 delete Op;
4193 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004194
4195 // The vector-compare-to-zero instructions have a literal token "#0" at
4196 // the end that comes to here as an immediate operand. Convert it to a
4197 // token to play nicely with the matcher.
4198 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4199 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4200 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4201 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4202 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4203 if (CE && CE->getValue() == 0) {
4204 Operands.erase(Operands.begin() + 5);
4205 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4206 delete Op;
4207 }
4208 }
Jim Grosbach68259142011-10-03 22:30:24 +00004209 // VCMP{E} does the same thing, but with a different operand count.
4210 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4211 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4212 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4213 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4214 if (CE && CE->getValue() == 0) {
4215 Operands.erase(Operands.begin() + 4);
4216 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4217 delete Op;
4218 }
4219 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004220 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4221 // end. Convert it to a token here.
4222 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4223 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4224 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4225 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4226 if (CE && CE->getValue() == 0) {
4227 Operands.erase(Operands.begin() + 5);
4228 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4229 delete Op;
4230 }
4231 }
4232
Chris Lattner98986712010-01-14 22:21:20 +00004233 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004234}
4235
Jim Grosbach189610f2011-07-26 18:25:39 +00004236// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004237
4238// return 'true' if register list contains non-low GPR registers,
4239// 'false' otherwise. If Reg is in the register list or is HiReg, set
4240// 'containsReg' to true.
4241static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4242 unsigned HiReg, bool &containsReg) {
4243 containsReg = false;
4244 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4245 unsigned OpReg = Inst.getOperand(i).getReg();
4246 if (OpReg == Reg)
4247 containsReg = true;
4248 // Anything other than a low register isn't legal here.
4249 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4250 return true;
4251 }
4252 return false;
4253}
4254
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004255// Check if the specified regisgter is in the register list of the inst,
4256// starting at the indicated operand number.
4257static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4258 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4259 unsigned OpReg = Inst.getOperand(i).getReg();
4260 if (OpReg == Reg)
4261 return true;
4262 }
4263 return false;
4264}
4265
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004266// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4267// the ARMInsts array) instead. Getting that here requires awkward
4268// API changes, though. Better way?
4269namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004270extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004271}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004272static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004273 return ARMInsts[Opcode];
4274}
4275
Jim Grosbach189610f2011-07-26 18:25:39 +00004276// FIXME: We would really like to be able to tablegen'erate this.
4277bool ARMAsmParser::
4278validateInstruction(MCInst &Inst,
4279 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004280 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004281 SMLoc Loc = Operands[0]->getStartLoc();
4282 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004283 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4284 // being allowed in IT blocks, but not being predicable. It just always
4285 // executes.
4286 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004287 unsigned bit = 1;
4288 if (ITState.FirstCond)
4289 ITState.FirstCond = false;
4290 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004291 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004292 // The instruction must be predicable.
4293 if (!MCID.isPredicable())
4294 return Error(Loc, "instructions in IT block must be predicable");
4295 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4296 unsigned ITCond = bit ? ITState.Cond :
4297 ARMCC::getOppositeCondition(ITState.Cond);
4298 if (Cond != ITCond) {
4299 // Find the condition code Operand to get its SMLoc information.
4300 SMLoc CondLoc;
4301 for (unsigned i = 1; i < Operands.size(); ++i)
4302 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4303 CondLoc = Operands[i]->getStartLoc();
4304 return Error(CondLoc, "incorrect condition in IT block; got '" +
4305 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4306 "', but expected '" +
4307 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4308 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004309 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004310 } else if (isThumbTwo() && MCID.isPredicable() &&
4311 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004312 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4313 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004314 return Error(Loc, "predicated instructions must be in IT block");
4315
Jim Grosbach189610f2011-07-26 18:25:39 +00004316 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004317 case ARM::LDRD:
4318 case ARM::LDRD_PRE:
4319 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004320 case ARM::LDREXD: {
4321 // Rt2 must be Rt + 1.
4322 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4323 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4324 if (Rt2 != Rt + 1)
4325 return Error(Operands[3]->getStartLoc(),
4326 "destination operands must be sequential");
4327 return false;
4328 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004329 case ARM::STRD: {
4330 // Rt2 must be Rt + 1.
4331 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4332 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4333 if (Rt2 != Rt + 1)
4334 return Error(Operands[3]->getStartLoc(),
4335 "source operands must be sequential");
4336 return false;
4337 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004338 case ARM::STRD_PRE:
4339 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004340 case ARM::STREXD: {
4341 // Rt2 must be Rt + 1.
4342 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4343 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4344 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004345 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004346 "source operands must be sequential");
4347 return false;
4348 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004349 case ARM::SBFX:
4350 case ARM::UBFX: {
4351 // width must be in range [1, 32-lsb]
4352 unsigned lsb = Inst.getOperand(2).getImm();
4353 unsigned widthm1 = Inst.getOperand(3).getImm();
4354 if (widthm1 >= 32 - lsb)
4355 return Error(Operands[5]->getStartLoc(),
4356 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004357 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004358 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004359 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004360 // If we're parsing Thumb2, the .w variant is available and handles
4361 // most cases that are normally illegal for a Thumb1 LDM
4362 // instruction. We'll make the transformation in processInstruction()
4363 // if necessary.
4364 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004365 // Thumb LDM instructions are writeback iff the base register is not
4366 // in the register list.
4367 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004368 bool hasWritebackToken =
4369 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4370 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004371 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004372 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004373 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4374 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004375 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004376 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004377 return Error(Operands[2]->getStartLoc(),
4378 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004379 // If we should not have writeback, there must not be a '!'. This is
4380 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004381 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004382 return Error(Operands[3]->getStartLoc(),
4383 "writeback operator '!' not allowed when base register "
4384 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004385
4386 break;
4387 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004388 case ARM::t2LDMIA_UPD: {
4389 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4390 return Error(Operands[4]->getStartLoc(),
4391 "writeback operator '!' not allowed when base register "
4392 "in register list");
4393 break;
4394 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004395 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004396 bool listContainsBase;
4397 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4398 return Error(Operands[2]->getStartLoc(),
4399 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004400 break;
4401 }
4402 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004403 bool listContainsBase;
4404 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4405 return Error(Operands[2]->getStartLoc(),
4406 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004407 break;
4408 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004409 case ARM::tSTMIA_UPD: {
4410 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004411 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004412 return Error(Operands[4]->getStartLoc(),
4413 "registers must be in range r0-r7");
4414 break;
4415 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004416 }
4417
4418 return false;
4419}
4420
Jim Grosbachf8fce712011-08-11 17:35:48 +00004421void ARMAsmParser::
4422processInstruction(MCInst &Inst,
4423 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4424 switch (Inst.getOpcode()) {
4425 case ARM::LDMIA_UPD:
4426 // If this is a load of a single register via a 'pop', then we should use
4427 // a post-indexed LDR instruction instead, per the ARM ARM.
4428 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4429 Inst.getNumOperands() == 5) {
4430 MCInst TmpInst;
4431 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4432 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4433 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4434 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4435 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4436 TmpInst.addOperand(MCOperand::CreateImm(4));
4437 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4438 TmpInst.addOperand(Inst.getOperand(3));
4439 Inst = TmpInst;
4440 }
4441 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004442 case ARM::STMDB_UPD:
4443 // If this is a store of a single register via a 'push', then we should use
4444 // a pre-indexed STR instruction instead, per the ARM ARM.
4445 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4446 Inst.getNumOperands() == 5) {
4447 MCInst TmpInst;
4448 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4449 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4450 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4451 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4452 TmpInst.addOperand(MCOperand::CreateImm(-4));
4453 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4454 TmpInst.addOperand(Inst.getOperand(3));
4455 Inst = TmpInst;
4456 }
4457 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004458 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004459 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4460 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4461 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4462 // to encoding T1 if <Rd> is omitted."
4463 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004464 Inst.setOpcode(ARM::tADDi3);
4465 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004466 case ARM::tSUBi8:
4467 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4468 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4469 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4470 // to encoding T1 if <Rd> is omitted."
4471 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4472 Inst.setOpcode(ARM::tSUBi3);
4473 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004474 case ARM::tB:
4475 // A Thumb conditional branch outside of an IT block is a tBcc.
4476 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4477 Inst.setOpcode(ARM::tBcc);
4478 break;
4479 case ARM::t2B:
4480 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4481 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4482 Inst.setOpcode(ARM::t2Bcc);
4483 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004484 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004485 // If the conditional is AL or we're in an IT block, we really want t2B.
4486 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004487 Inst.setOpcode(ARM::t2B);
4488 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004489 case ARM::tBcc:
4490 // If the conditional is AL, we really want tB.
4491 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4492 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004493 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004494 case ARM::tLDMIA: {
4495 // If the register list contains any high registers, or if the writeback
4496 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4497 // instead if we're in Thumb2. Otherwise, this should have generated
4498 // an error in validateInstruction().
4499 unsigned Rn = Inst.getOperand(0).getReg();
4500 bool hasWritebackToken =
4501 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4502 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4503 bool listContainsBase;
4504 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4505 (!listContainsBase && !hasWritebackToken) ||
4506 (listContainsBase && hasWritebackToken)) {
4507 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4508 assert (isThumbTwo());
4509 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4510 // If we're switching to the updating version, we need to insert
4511 // the writeback tied operand.
4512 if (hasWritebackToken)
4513 Inst.insert(Inst.begin(),
4514 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4515 }
4516 break;
4517 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004518 case ARM::tSTMIA_UPD: {
4519 // If the register list contains any high registers, we need to use
4520 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4521 // should have generated an error in validateInstruction().
4522 unsigned Rn = Inst.getOperand(0).getReg();
4523 bool listContainsBase;
4524 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4525 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4526 assert (isThumbTwo());
4527 Inst.setOpcode(ARM::t2STMIA_UPD);
4528 }
4529 break;
4530 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004531 case ARM::t2MOVi: {
4532 // If we can use the 16-bit encoding and the user didn't explicitly
4533 // request the 32-bit variant, transform it here.
4534 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4535 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004536 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4537 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4538 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004539 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4540 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4541 // The operands aren't in the same order for tMOVi8...
4542 MCInst TmpInst;
4543 TmpInst.setOpcode(ARM::tMOVi8);
4544 TmpInst.addOperand(Inst.getOperand(0));
4545 TmpInst.addOperand(Inst.getOperand(4));
4546 TmpInst.addOperand(Inst.getOperand(1));
4547 TmpInst.addOperand(Inst.getOperand(2));
4548 TmpInst.addOperand(Inst.getOperand(3));
4549 Inst = TmpInst;
4550 }
4551 break;
4552 }
4553 case ARM::t2MOVr: {
4554 // If we can use the 16-bit encoding and the user didn't explicitly
4555 // request the 32-bit variant, transform it here.
4556 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4557 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4558 Inst.getOperand(2).getImm() == ARMCC::AL &&
4559 Inst.getOperand(4).getReg() == ARM::CPSR &&
4560 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4561 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4562 // The operands aren't the same for tMOV[S]r... (no cc_out)
4563 MCInst TmpInst;
4564 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4565 TmpInst.addOperand(Inst.getOperand(0));
4566 TmpInst.addOperand(Inst.getOperand(1));
4567 TmpInst.addOperand(Inst.getOperand(2));
4568 TmpInst.addOperand(Inst.getOperand(3));
4569 Inst = TmpInst;
4570 }
4571 break;
4572 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004573 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004574 case ARM::t2SXTB:
4575 case ARM::t2UXTH:
4576 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004577 // If we can use the 16-bit encoding and the user didn't explicitly
4578 // request the 32-bit variant, transform it here.
4579 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4580 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4581 Inst.getOperand(2).getImm() == 0 &&
4582 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4583 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004584 unsigned NewOpc;
4585 switch (Inst.getOpcode()) {
4586 default: llvm_unreachable("Illegal opcode!");
4587 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4588 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4589 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4590 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4591 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004592 // The operands aren't the same for thumb1 (no rotate operand).
4593 MCInst TmpInst;
4594 TmpInst.setOpcode(NewOpc);
4595 TmpInst.addOperand(Inst.getOperand(0));
4596 TmpInst.addOperand(Inst.getOperand(1));
4597 TmpInst.addOperand(Inst.getOperand(3));
4598 TmpInst.addOperand(Inst.getOperand(4));
4599 Inst = TmpInst;
4600 }
4601 break;
4602 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004603 case ARM::t2IT: {
4604 // The mask bits for all but the first condition are represented as
4605 // the low bit of the condition code value implies 't'. We currently
4606 // always have 1 implies 't', so XOR toggle the bits if the low bit
4607 // of the condition code is zero. The encoding also expects the low
4608 // bit of the condition to be encoded as bit 4 of the mask operand,
4609 // so mask that in if needed
4610 MCOperand &MO = Inst.getOperand(1);
4611 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004612 unsigned OrigMask = Mask;
4613 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004614 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004615 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4616 for (unsigned i = 3; i != TZ; --i)
4617 Mask ^= 1 << i;
4618 } else
4619 Mask |= 0x10;
4620 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004621
4622 // Set up the IT block state according to the IT instruction we just
4623 // matched.
4624 assert(!inITBlock() && "nested IT blocks?!");
4625 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4626 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4627 ITState.CurPosition = 0;
4628 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004629 break;
4630 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004631 }
4632}
4633
Jim Grosbach47a0d522011-08-16 20:45:50 +00004634unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4635 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4636 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004637 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004638 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004639 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4640 assert(MCID.hasOptionalDef() &&
4641 "optionally flag setting instruction missing optional def operand");
4642 assert(MCID.NumOperands == Inst.getNumOperands() &&
4643 "operand count mismatch!");
4644 // Find the optional-def operand (cc_out).
4645 unsigned OpNo;
4646 for (OpNo = 0;
4647 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4648 ++OpNo)
4649 ;
4650 // If we're parsing Thumb1, reject it completely.
4651 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4652 return Match_MnemonicFail;
4653 // If we're parsing Thumb2, which form is legal depends on whether we're
4654 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004655 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4656 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004657 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004658 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4659 inITBlock())
4660 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004661 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004662 // Some high-register supporting Thumb1 encodings only allow both registers
4663 // to be from r0-r7 when in Thumb2.
4664 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4665 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4666 isARMLowRegister(Inst.getOperand(2).getReg()))
4667 return Match_RequiresThumb2;
4668 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004669 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004670 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4671 isARMLowRegister(Inst.getOperand(1).getReg()))
4672 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004673 return Match_Success;
4674}
4675
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004676bool ARMAsmParser::
4677MatchAndEmitInstruction(SMLoc IDLoc,
4678 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4679 MCStreamer &Out) {
4680 MCInst Inst;
4681 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004682 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004683 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004684 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004685 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004686 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004687 // Context sensitive operand constraints aren't handled by the matcher,
4688 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004689 if (validateInstruction(Inst, Operands)) {
4690 // Still progress the IT block, otherwise one wrong condition causes
4691 // nasty cascading errors.
4692 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004693 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004694 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004695
Jim Grosbachf8fce712011-08-11 17:35:48 +00004696 // Some instructions need post-processing to, for example, tweak which
4697 // encoding is selected.
4698 processInstruction(Inst, Operands);
4699
Jim Grosbacha1109882011-09-02 23:22:08 +00004700 // Only move forward at the very end so that everything in validate
4701 // and process gets a consistent answer about whether we're in an IT
4702 // block.
4703 forwardITPosition();
4704
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004705 Out.EmitInstruction(Inst);
4706 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004707 case Match_MissingFeature:
4708 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4709 return true;
4710 case Match_InvalidOperand: {
4711 SMLoc ErrorLoc = IDLoc;
4712 if (ErrorInfo != ~0U) {
4713 if (ErrorInfo >= Operands.size())
4714 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004715
Chris Lattnere73d4f82010-10-28 21:41:58 +00004716 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4717 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4718 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004719
Chris Lattnere73d4f82010-10-28 21:41:58 +00004720 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004721 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004722 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004723 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004724 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004725 // The converter function will have already emited a diagnostic.
4726 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004727 case Match_RequiresNotITBlock:
4728 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004729 case Match_RequiresITBlock:
4730 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004731 case Match_RequiresV6:
4732 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4733 case Match_RequiresThumb2:
4734 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004735 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004736
Eric Christopherc223e2b2010-10-29 09:26:59 +00004737 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004738 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004739}
4740
Jim Grosbach1355cf12011-07-26 17:10:22 +00004741/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004742bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4743 StringRef IDVal = DirectiveID.getIdentifier();
4744 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004745 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004746 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004747 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004748 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004749 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004750 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004751 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004752 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004753 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004754 return true;
4755}
4756
Jim Grosbach1355cf12011-07-26 17:10:22 +00004757/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004758/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004759bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004760 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4761 for (;;) {
4762 const MCExpr *Value;
4763 if (getParser().ParseExpression(Value))
4764 return true;
4765
Chris Lattneraaec2052010-01-19 19:46:13 +00004766 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004767
4768 if (getLexer().is(AsmToken::EndOfStatement))
4769 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004770
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004771 // FIXME: Improve diagnostic.
4772 if (getLexer().isNot(AsmToken::Comma))
4773 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004774 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004775 }
4776 }
4777
Sean Callananb9a25b72010-01-19 20:27:46 +00004778 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004779 return false;
4780}
4781
Jim Grosbach1355cf12011-07-26 17:10:22 +00004782/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004783/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004784bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004785 if (getLexer().isNot(AsmToken::EndOfStatement))
4786 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004787 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004788
4789 // TODO: set thumb mode
4790 // TODO: tell the MC streamer the mode
4791 // getParser().getStreamer().Emit???();
4792 return false;
4793}
4794
Jim Grosbach1355cf12011-07-26 17:10:22 +00004795/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004796/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004797bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004798 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4799 bool isMachO = MAI.hasSubsectionsViaSymbols();
4800 StringRef Name;
4801
4802 // Darwin asm has function name after .thumb_func direction
4803 // ELF doesn't
4804 if (isMachO) {
4805 const AsmToken &Tok = Parser.getTok();
4806 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4807 return Error(L, "unexpected token in .thumb_func directive");
4808 Name = Tok.getString();
4809 Parser.Lex(); // Consume the identifier token.
4810 }
4811
Kevin Enderby515d5092009-10-15 20:48:48 +00004812 if (getLexer().isNot(AsmToken::EndOfStatement))
4813 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004814 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004815
Rafael Espindola64695402011-05-16 16:17:21 +00004816 // FIXME: assuming function name will be the line following .thumb_func
4817 if (!isMachO) {
4818 Name = Parser.getTok().getString();
4819 }
4820
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004821 // Mark symbol as a thumb symbol.
4822 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4823 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004824 return false;
4825}
4826
Jim Grosbach1355cf12011-07-26 17:10:22 +00004827/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004828/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004829bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004830 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004831 if (Tok.isNot(AsmToken::Identifier))
4832 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004833 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004834 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004835 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004836 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004837 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004838 else
4839 return Error(L, "unrecognized syntax mode in .syntax directive");
4840
4841 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004842 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004843 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004844
4845 // TODO tell the MC streamer the mode
4846 // getParser().getStreamer().Emit???();
4847 return false;
4848}
4849
Jim Grosbach1355cf12011-07-26 17:10:22 +00004850/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004851/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004852bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004853 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004854 if (Tok.isNot(AsmToken::Integer))
4855 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004856 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004857 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004858 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004859 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004860 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004861 else
4862 return Error(L, "invalid operand to .code directive");
4863
4864 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004865 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004866 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004867
Evan Cheng32869202011-07-08 22:36:29 +00004868 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004869 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004870 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004871 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004872 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004873 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004874 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004875 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004876 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004877
Kevin Enderby515d5092009-10-15 20:48:48 +00004878 return false;
4879}
4880
Sean Callanan90b70972010-04-07 20:29:34 +00004881extern "C" void LLVMInitializeARMAsmLexer();
4882
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004883/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004884extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004885 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4886 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004887 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004888}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004889
Chris Lattner0692ee62010-09-06 19:11:01 +00004890#define GET_REGISTER_MATCHER
4891#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004892#include "ARMGenAsmMatcher.inc"