blob: dbdce29e10778f3fe468022f32dc50e289dfcdd7 [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 Grosbachc73d73e2011-10-28 00:06:50 +00002443// Return the low-subreg of a given Q register.
2444static unsigned getDRegFromQReg(unsigned QReg) {
2445 switch (QReg) {
2446 default: llvm_unreachable("expected a Q register!");
2447 case ARM::Q0: return ARM::D0;
2448 case ARM::Q1: return ARM::D2;
2449 case ARM::Q2: return ARM::D4;
2450 case ARM::Q3: return ARM::D6;
2451 case ARM::Q4: return ARM::D8;
2452 case ARM::Q5: return ARM::D10;
2453 case ARM::Q6: return ARM::D12;
2454 case ARM::Q7: return ARM::D14;
2455 case ARM::Q8: return ARM::D16;
2456 case ARM::Q9: return ARM::D19;
2457 case ARM::Q10: return ARM::D20;
2458 case ARM::Q11: return ARM::D22;
2459 case ARM::Q12: return ARM::D24;
2460 case ARM::Q13: return ARM::D26;
2461 case ARM::Q14: return ARM::D28;
2462 case ARM::Q15: return ARM::D30;
2463 }
2464}
2465
Jim Grosbach862019c2011-10-18 23:02:30 +00002466// parse a vector register list
2467ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2468parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2469 if(Parser.getTok().isNot(AsmToken::LCurly))
2470 return MatchOperand_NoMatch;
2471
2472 SMLoc S = Parser.getTok().getLoc();
2473 Parser.Lex(); // Eat '{' token.
2474 SMLoc RegLoc = Parser.getTok().getLoc();
2475
2476 int Reg = tryParseRegister();
2477 if (Reg == -1) {
2478 Error(RegLoc, "register expected");
2479 return MatchOperand_ParseFail;
2480 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002481 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002482 unsigned FirstReg = Reg;
2483 // The list is of D registers, but we also allow Q regs and just interpret
2484 // them as the two D sub-registers.
2485 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2486 FirstReg = Reg = getDRegFromQReg(Reg);
2487 ++Reg;
2488 ++Count;
2489 }
2490
Jim Grosbach862019c2011-10-18 23:02:30 +00002491 while (Parser.getTok().is(AsmToken::Comma)) {
2492 Parser.Lex(); // Eat the comma.
2493 RegLoc = Parser.getTok().getLoc();
2494 int OldReg = Reg;
2495 Reg = tryParseRegister();
2496 if (Reg == -1) {
2497 Error(RegLoc, "register expected");
2498 return MatchOperand_ParseFail;
2499 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002500 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002501 // It's OK to use the enumeration values directly here rather, as the
2502 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002503 //
2504 // The list is of D registers, but we also allow Q regs and just interpret
2505 // them as the two D sub-registers.
2506 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2507 Reg = getDRegFromQReg(Reg);
2508 if (Reg != OldReg + 1) {
2509 Error(RegLoc, "non-contiguous register range");
2510 return MatchOperand_ParseFail;
2511 }
2512 ++Reg;
2513 Count += 2;
2514 continue;
2515 }
2516 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002517 if (Reg != OldReg + 1) {
2518 Error(RegLoc, "non-contiguous register range");
2519 return MatchOperand_ParseFail;
2520 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002521 ++Count;
2522 }
2523
2524 SMLoc E = Parser.getTok().getLoc();
2525 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2526 Error(E, "'}' expected");
2527 return MatchOperand_ParseFail;
2528 }
2529 Parser.Lex(); // Eat '}' token.
2530
2531 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2532 return MatchOperand_Success;
2533}
2534
Jim Grosbach43904292011-07-25 20:14:50 +00002535/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002536ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002537parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002538 SMLoc S = Parser.getTok().getLoc();
2539 const AsmToken &Tok = Parser.getTok();
2540 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2541 StringRef OptStr = Tok.getString();
2542
2543 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2544 .Case("sy", ARM_MB::SY)
2545 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002546 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002547 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002548 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002549 .Case("ishst", ARM_MB::ISHST)
2550 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002551 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002552 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002553 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002554 .Case("osh", ARM_MB::OSH)
2555 .Case("oshst", ARM_MB::OSHST)
2556 .Default(~0U);
2557
2558 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002559 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002560
2561 Parser.Lex(); // Eat identifier token.
2562 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002563 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002564}
2565
Jim Grosbach43904292011-07-25 20:14:50 +00002566/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002567ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002568parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002569 SMLoc S = Parser.getTok().getLoc();
2570 const AsmToken &Tok = Parser.getTok();
2571 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2572 StringRef IFlagsStr = Tok.getString();
2573
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002574 // An iflags string of "none" is interpreted to mean that none of the AIF
2575 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002576 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002577 if (IFlagsStr != "none") {
2578 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2579 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2580 .Case("a", ARM_PROC::A)
2581 .Case("i", ARM_PROC::I)
2582 .Case("f", ARM_PROC::F)
2583 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002584
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002585 // If some specific iflag is already set, it means that some letter is
2586 // present more than once, this is not acceptable.
2587 if (Flag == ~0U || (IFlags & Flag))
2588 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002589
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002590 IFlags |= Flag;
2591 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002592 }
2593
2594 Parser.Lex(); // Eat identifier token.
2595 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2596 return MatchOperand_Success;
2597}
2598
Jim Grosbach43904292011-07-25 20:14:50 +00002599/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002600ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002601parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002602 SMLoc S = Parser.getTok().getLoc();
2603 const AsmToken &Tok = Parser.getTok();
2604 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2605 StringRef Mask = Tok.getString();
2606
James Molloyacad68d2011-09-28 14:21:38 +00002607 if (isMClass()) {
2608 // See ARMv6-M 10.1.1
2609 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2610 .Case("apsr", 0)
2611 .Case("iapsr", 1)
2612 .Case("eapsr", 2)
2613 .Case("xpsr", 3)
2614 .Case("ipsr", 5)
2615 .Case("epsr", 6)
2616 .Case("iepsr", 7)
2617 .Case("msp", 8)
2618 .Case("psp", 9)
2619 .Case("primask", 16)
2620 .Case("basepri", 17)
2621 .Case("basepri_max", 18)
2622 .Case("faultmask", 19)
2623 .Case("control", 20)
2624 .Default(~0U);
2625
2626 if (FlagsVal == ~0U)
2627 return MatchOperand_NoMatch;
2628
2629 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2630 // basepri, basepri_max and faultmask only valid for V7m.
2631 return MatchOperand_NoMatch;
2632
2633 Parser.Lex(); // Eat identifier token.
2634 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2635 return MatchOperand_Success;
2636 }
2637
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002638 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2639 size_t Start = 0, Next = Mask.find('_');
2640 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002641 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002642 if (Next != StringRef::npos)
2643 Flags = Mask.slice(Next+1, Mask.size());
2644
2645 // FlagsVal contains the complete mask:
2646 // 3-0: Mask
2647 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2648 unsigned FlagsVal = 0;
2649
2650 if (SpecReg == "apsr") {
2651 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002652 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002653 .Case("g", 0x4) // same as CPSR_s
2654 .Case("nzcvqg", 0xc) // same as CPSR_fs
2655 .Default(~0U);
2656
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002657 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002658 if (!Flags.empty())
2659 return MatchOperand_NoMatch;
2660 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002661 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002662 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002663 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002664 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2665 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002666 for (int i = 0, e = Flags.size(); i != e; ++i) {
2667 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2668 .Case("c", 1)
2669 .Case("x", 2)
2670 .Case("s", 4)
2671 .Case("f", 8)
2672 .Default(~0U);
2673
2674 // If some specific flag is already set, it means that some letter is
2675 // present more than once, this is not acceptable.
2676 if (FlagsVal == ~0U || (FlagsVal & Flag))
2677 return MatchOperand_NoMatch;
2678 FlagsVal |= Flag;
2679 }
2680 } else // No match for special register.
2681 return MatchOperand_NoMatch;
2682
Owen Anderson7784f1d2011-10-21 18:43:28 +00002683 // Special register without flags is NOT equivalent to "fc" flags.
2684 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2685 // two lines would enable gas compatibility at the expense of breaking
2686 // round-tripping.
2687 //
2688 // if (!FlagsVal)
2689 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002690
2691 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2692 if (SpecReg == "spsr")
2693 FlagsVal |= 16;
2694
2695 Parser.Lex(); // Eat identifier token.
2696 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2697 return MatchOperand_Success;
2698}
2699
Jim Grosbachf6c05252011-07-21 17:23:04 +00002700ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2701parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2702 int Low, int High) {
2703 const AsmToken &Tok = Parser.getTok();
2704 if (Tok.isNot(AsmToken::Identifier)) {
2705 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2706 return MatchOperand_ParseFail;
2707 }
2708 StringRef ShiftName = Tok.getString();
2709 std::string LowerOp = LowercaseString(Op);
2710 std::string UpperOp = UppercaseString(Op);
2711 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2712 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2713 return MatchOperand_ParseFail;
2714 }
2715 Parser.Lex(); // Eat shift type token.
2716
2717 // There must be a '#' and a shift amount.
2718 if (Parser.getTok().isNot(AsmToken::Hash)) {
2719 Error(Parser.getTok().getLoc(), "'#' expected");
2720 return MatchOperand_ParseFail;
2721 }
2722 Parser.Lex(); // Eat hash token.
2723
2724 const MCExpr *ShiftAmount;
2725 SMLoc Loc = Parser.getTok().getLoc();
2726 if (getParser().ParseExpression(ShiftAmount)) {
2727 Error(Loc, "illegal expression");
2728 return MatchOperand_ParseFail;
2729 }
2730 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2731 if (!CE) {
2732 Error(Loc, "constant expression expected");
2733 return MatchOperand_ParseFail;
2734 }
2735 int Val = CE->getValue();
2736 if (Val < Low || Val > High) {
2737 Error(Loc, "immediate value out of range");
2738 return MatchOperand_ParseFail;
2739 }
2740
2741 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2742
2743 return MatchOperand_Success;
2744}
2745
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002746ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2747parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2748 const AsmToken &Tok = Parser.getTok();
2749 SMLoc S = Tok.getLoc();
2750 if (Tok.isNot(AsmToken::Identifier)) {
2751 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2752 return MatchOperand_ParseFail;
2753 }
2754 int Val = StringSwitch<int>(Tok.getString())
2755 .Case("be", 1)
2756 .Case("le", 0)
2757 .Default(-1);
2758 Parser.Lex(); // Eat the token.
2759
2760 if (Val == -1) {
2761 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2762 return MatchOperand_ParseFail;
2763 }
2764 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2765 getContext()),
2766 S, Parser.getTok().getLoc()));
2767 return MatchOperand_Success;
2768}
2769
Jim Grosbach580f4a92011-07-25 22:20:28 +00002770/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2771/// instructions. Legal values are:
2772/// lsl #n 'n' in [0,31]
2773/// asr #n 'n' in [1,32]
2774/// n == 32 encoded as n == 0.
2775ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2776parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2777 const AsmToken &Tok = Parser.getTok();
2778 SMLoc S = Tok.getLoc();
2779 if (Tok.isNot(AsmToken::Identifier)) {
2780 Error(S, "shift operator 'asr' or 'lsl' expected");
2781 return MatchOperand_ParseFail;
2782 }
2783 StringRef ShiftName = Tok.getString();
2784 bool isASR;
2785 if (ShiftName == "lsl" || ShiftName == "LSL")
2786 isASR = false;
2787 else if (ShiftName == "asr" || ShiftName == "ASR")
2788 isASR = true;
2789 else {
2790 Error(S, "shift operator 'asr' or 'lsl' expected");
2791 return MatchOperand_ParseFail;
2792 }
2793 Parser.Lex(); // Eat the operator.
2794
2795 // A '#' and a shift amount.
2796 if (Parser.getTok().isNot(AsmToken::Hash)) {
2797 Error(Parser.getTok().getLoc(), "'#' expected");
2798 return MatchOperand_ParseFail;
2799 }
2800 Parser.Lex(); // Eat hash token.
2801
2802 const MCExpr *ShiftAmount;
2803 SMLoc E = Parser.getTok().getLoc();
2804 if (getParser().ParseExpression(ShiftAmount)) {
2805 Error(E, "malformed shift expression");
2806 return MatchOperand_ParseFail;
2807 }
2808 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2809 if (!CE) {
2810 Error(E, "shift amount must be an immediate");
2811 return MatchOperand_ParseFail;
2812 }
2813
2814 int64_t Val = CE->getValue();
2815 if (isASR) {
2816 // Shift amount must be in [1,32]
2817 if (Val < 1 || Val > 32) {
2818 Error(E, "'asr' shift amount must be in range [1,32]");
2819 return MatchOperand_ParseFail;
2820 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002821 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2822 if (isThumb() && Val == 32) {
2823 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2824 return MatchOperand_ParseFail;
2825 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002826 if (Val == 32) Val = 0;
2827 } else {
2828 // Shift amount must be in [1,32]
2829 if (Val < 0 || Val > 31) {
2830 Error(E, "'lsr' shift amount must be in range [0,31]");
2831 return MatchOperand_ParseFail;
2832 }
2833 }
2834
2835 E = Parser.getTok().getLoc();
2836 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2837
2838 return MatchOperand_Success;
2839}
2840
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002841/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2842/// of instructions. Legal values are:
2843/// ror #n 'n' in {0, 8, 16, 24}
2844ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2845parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2846 const AsmToken &Tok = Parser.getTok();
2847 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002848 if (Tok.isNot(AsmToken::Identifier))
2849 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002850 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002851 if (ShiftName != "ror" && ShiftName != "ROR")
2852 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002853 Parser.Lex(); // Eat the operator.
2854
2855 // A '#' and a rotate amount.
2856 if (Parser.getTok().isNot(AsmToken::Hash)) {
2857 Error(Parser.getTok().getLoc(), "'#' expected");
2858 return MatchOperand_ParseFail;
2859 }
2860 Parser.Lex(); // Eat hash token.
2861
2862 const MCExpr *ShiftAmount;
2863 SMLoc E = Parser.getTok().getLoc();
2864 if (getParser().ParseExpression(ShiftAmount)) {
2865 Error(E, "malformed rotate expression");
2866 return MatchOperand_ParseFail;
2867 }
2868 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2869 if (!CE) {
2870 Error(E, "rotate amount must be an immediate");
2871 return MatchOperand_ParseFail;
2872 }
2873
2874 int64_t Val = CE->getValue();
2875 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2876 // normally, zero is represented in asm by omitting the rotate operand
2877 // entirely.
2878 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2879 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2880 return MatchOperand_ParseFail;
2881 }
2882
2883 E = Parser.getTok().getLoc();
2884 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2885
2886 return MatchOperand_Success;
2887}
2888
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002889ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2890parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2891 SMLoc S = Parser.getTok().getLoc();
2892 // The bitfield descriptor is really two operands, the LSB and the width.
2893 if (Parser.getTok().isNot(AsmToken::Hash)) {
2894 Error(Parser.getTok().getLoc(), "'#' expected");
2895 return MatchOperand_ParseFail;
2896 }
2897 Parser.Lex(); // Eat hash token.
2898
2899 const MCExpr *LSBExpr;
2900 SMLoc E = Parser.getTok().getLoc();
2901 if (getParser().ParseExpression(LSBExpr)) {
2902 Error(E, "malformed immediate expression");
2903 return MatchOperand_ParseFail;
2904 }
2905 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2906 if (!CE) {
2907 Error(E, "'lsb' operand must be an immediate");
2908 return MatchOperand_ParseFail;
2909 }
2910
2911 int64_t LSB = CE->getValue();
2912 // The LSB must be in the range [0,31]
2913 if (LSB < 0 || LSB > 31) {
2914 Error(E, "'lsb' operand must be in the range [0,31]");
2915 return MatchOperand_ParseFail;
2916 }
2917 E = Parser.getTok().getLoc();
2918
2919 // Expect another immediate operand.
2920 if (Parser.getTok().isNot(AsmToken::Comma)) {
2921 Error(Parser.getTok().getLoc(), "too few operands");
2922 return MatchOperand_ParseFail;
2923 }
2924 Parser.Lex(); // Eat hash token.
2925 if (Parser.getTok().isNot(AsmToken::Hash)) {
2926 Error(Parser.getTok().getLoc(), "'#' expected");
2927 return MatchOperand_ParseFail;
2928 }
2929 Parser.Lex(); // Eat hash token.
2930
2931 const MCExpr *WidthExpr;
2932 if (getParser().ParseExpression(WidthExpr)) {
2933 Error(E, "malformed immediate expression");
2934 return MatchOperand_ParseFail;
2935 }
2936 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2937 if (!CE) {
2938 Error(E, "'width' operand must be an immediate");
2939 return MatchOperand_ParseFail;
2940 }
2941
2942 int64_t Width = CE->getValue();
2943 // The LSB must be in the range [1,32-lsb]
2944 if (Width < 1 || Width > 32 - LSB) {
2945 Error(E, "'width' operand must be in the range [1,32-lsb]");
2946 return MatchOperand_ParseFail;
2947 }
2948 E = Parser.getTok().getLoc();
2949
2950 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2951
2952 return MatchOperand_Success;
2953}
2954
Jim Grosbach7ce05792011-08-03 23:50:40 +00002955ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2956parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2957 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002958 // postidx_reg := '+' register {, shift}
2959 // | '-' register {, shift}
2960 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002961
2962 // This method must return MatchOperand_NoMatch without consuming any tokens
2963 // in the case where there is no match, as other alternatives take other
2964 // parse methods.
2965 AsmToken Tok = Parser.getTok();
2966 SMLoc S = Tok.getLoc();
2967 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002968 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002969 int Reg = -1;
2970 if (Tok.is(AsmToken::Plus)) {
2971 Parser.Lex(); // Eat the '+' token.
2972 haveEaten = true;
2973 } else if (Tok.is(AsmToken::Minus)) {
2974 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002975 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002976 haveEaten = true;
2977 }
2978 if (Parser.getTok().is(AsmToken::Identifier))
2979 Reg = tryParseRegister();
2980 if (Reg == -1) {
2981 if (!haveEaten)
2982 return MatchOperand_NoMatch;
2983 Error(Parser.getTok().getLoc(), "register expected");
2984 return MatchOperand_ParseFail;
2985 }
2986 SMLoc E = Parser.getTok().getLoc();
2987
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002988 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2989 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002990 if (Parser.getTok().is(AsmToken::Comma)) {
2991 Parser.Lex(); // Eat the ','.
2992 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2993 return MatchOperand_ParseFail;
2994 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002995
2996 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2997 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002998
2999 return MatchOperand_Success;
3000}
3001
Jim Grosbach251bf252011-08-10 21:56:18 +00003002ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3003parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3004 // Check for a post-index addressing register operand. Specifically:
3005 // am3offset := '+' register
3006 // | '-' register
3007 // | register
3008 // | # imm
3009 // | # + imm
3010 // | # - imm
3011
3012 // This method must return MatchOperand_NoMatch without consuming any tokens
3013 // in the case where there is no match, as other alternatives take other
3014 // parse methods.
3015 AsmToken Tok = Parser.getTok();
3016 SMLoc S = Tok.getLoc();
3017
3018 // Do immediates first, as we always parse those if we have a '#'.
3019 if (Parser.getTok().is(AsmToken::Hash)) {
3020 Parser.Lex(); // Eat the '#'.
3021 // Explicitly look for a '-', as we need to encode negative zero
3022 // differently.
3023 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3024 const MCExpr *Offset;
3025 if (getParser().ParseExpression(Offset))
3026 return MatchOperand_ParseFail;
3027 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3028 if (!CE) {
3029 Error(S, "constant expression expected");
3030 return MatchOperand_ParseFail;
3031 }
3032 SMLoc E = Tok.getLoc();
3033 // Negative zero is encoded as the flag value INT32_MIN.
3034 int32_t Val = CE->getValue();
3035 if (isNegative && Val == 0)
3036 Val = INT32_MIN;
3037
3038 Operands.push_back(
3039 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3040
3041 return MatchOperand_Success;
3042 }
3043
3044
3045 bool haveEaten = false;
3046 bool isAdd = true;
3047 int Reg = -1;
3048 if (Tok.is(AsmToken::Plus)) {
3049 Parser.Lex(); // Eat the '+' token.
3050 haveEaten = true;
3051 } else if (Tok.is(AsmToken::Minus)) {
3052 Parser.Lex(); // Eat the '-' token.
3053 isAdd = false;
3054 haveEaten = true;
3055 }
3056 if (Parser.getTok().is(AsmToken::Identifier))
3057 Reg = tryParseRegister();
3058 if (Reg == -1) {
3059 if (!haveEaten)
3060 return MatchOperand_NoMatch;
3061 Error(Parser.getTok().getLoc(), "register expected");
3062 return MatchOperand_ParseFail;
3063 }
3064 SMLoc E = Parser.getTok().getLoc();
3065
3066 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3067 0, S, E));
3068
3069 return MatchOperand_Success;
3070}
3071
Jim Grosbacha77295d2011-09-08 22:07:06 +00003072/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3073/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3074/// when they refer multiple MIOperands inside a single one.
3075bool ARMAsmParser::
3076cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3077 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3078 // Rt, Rt2
3079 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3080 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3081 // Create a writeback register dummy placeholder.
3082 Inst.addOperand(MCOperand::CreateReg(0));
3083 // addr
3084 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3085 // pred
3086 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3087 return true;
3088}
3089
3090/// cvtT2StrdPre - Convert parsed operands to MCInst.
3091/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3092/// when they refer multiple MIOperands inside a single one.
3093bool ARMAsmParser::
3094cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3095 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3096 // Create a writeback register dummy placeholder.
3097 Inst.addOperand(MCOperand::CreateReg(0));
3098 // Rt, Rt2
3099 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3100 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3101 // addr
3102 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3103 // pred
3104 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3105 return true;
3106}
3107
Jim Grosbacheeec0252011-09-08 00:39:19 +00003108/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3109/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3110/// when they refer multiple MIOperands inside a single one.
3111bool ARMAsmParser::
3112cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3113 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3114 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3115
3116 // Create a writeback register dummy placeholder.
3117 Inst.addOperand(MCOperand::CreateImm(0));
3118
3119 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3120 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3121 return true;
3122}
3123
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003124/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3125/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3126/// when they refer multiple MIOperands inside a single one.
3127bool ARMAsmParser::
3128cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3129 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3130 // Create a writeback register dummy placeholder.
3131 Inst.addOperand(MCOperand::CreateImm(0));
3132 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3133 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3134 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3135 return true;
3136}
3137
Jim Grosbach1355cf12011-07-26 17:10:22 +00003138/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003139/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3140/// when they refer multiple MIOperands inside a single one.
3141bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003142cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003143 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3144 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3145
3146 // Create a writeback register dummy placeholder.
3147 Inst.addOperand(MCOperand::CreateImm(0));
3148
Jim Grosbach7ce05792011-08-03 23:50:40 +00003149 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003150 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3151 return true;
3152}
3153
Owen Anderson9ab0f252011-08-26 20:43:14 +00003154/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3155/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3156/// when they refer multiple MIOperands inside a single one.
3157bool ARMAsmParser::
3158cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3159 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3160 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3161
3162 // Create a writeback register dummy placeholder.
3163 Inst.addOperand(MCOperand::CreateImm(0));
3164
3165 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3166 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3167 return true;
3168}
3169
3170
Jim Grosbach548340c2011-08-11 19:22:40 +00003171/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3172/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3173/// when they refer multiple MIOperands inside a single one.
3174bool ARMAsmParser::
3175cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3176 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3177 // Create a writeback register dummy placeholder.
3178 Inst.addOperand(MCOperand::CreateImm(0));
3179 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3180 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3181 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3182 return true;
3183}
3184
Jim Grosbach1355cf12011-07-26 17:10:22 +00003185/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003186/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3187/// when they refer multiple MIOperands inside a single one.
3188bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003189cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003190 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3191 // Create a writeback register dummy placeholder.
3192 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003193 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3194 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3195 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003196 return true;
3197}
3198
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003199/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3200/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3201/// when they refer multiple MIOperands inside a single one.
3202bool ARMAsmParser::
3203cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3204 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3205 // Create a writeback register dummy placeholder.
3206 Inst.addOperand(MCOperand::CreateImm(0));
3207 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3208 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3209 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3210 return true;
3211}
3212
Jim Grosbach7ce05792011-08-03 23:50:40 +00003213/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3214/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3215/// when they refer multiple MIOperands inside a single one.
3216bool ARMAsmParser::
3217cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3218 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3219 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003220 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003221 // Create a writeback register dummy placeholder.
3222 Inst.addOperand(MCOperand::CreateImm(0));
3223 // addr
3224 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3225 // offset
3226 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3227 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003228 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3229 return true;
3230}
3231
Jim Grosbach7ce05792011-08-03 23:50:40 +00003232/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003233/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3234/// when they refer multiple MIOperands inside a single one.
3235bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003236cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3237 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3238 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003239 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003240 // Create a writeback register dummy placeholder.
3241 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003242 // addr
3243 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3244 // offset
3245 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3246 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003247 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3248 return true;
3249}
3250
Jim Grosbach7ce05792011-08-03 23:50:40 +00003251/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003252/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3253/// when they refer multiple MIOperands inside a single one.
3254bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003255cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3256 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003257 // Create a writeback register dummy placeholder.
3258 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003259 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003260 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003261 // addr
3262 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3263 // offset
3264 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3265 // pred
3266 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3267 return true;
3268}
3269
3270/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3271/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3272/// when they refer multiple MIOperands inside a single one.
3273bool ARMAsmParser::
3274cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3275 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3276 // Create a writeback register dummy placeholder.
3277 Inst.addOperand(MCOperand::CreateImm(0));
3278 // Rt
3279 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3280 // addr
3281 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3282 // offset
3283 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3284 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003285 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3286 return true;
3287}
3288
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003289/// cvtLdrdPre - Convert parsed operands to MCInst.
3290/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3291/// when they refer multiple MIOperands inside a single one.
3292bool ARMAsmParser::
3293cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3294 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3295 // Rt, Rt2
3296 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3297 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3298 // Create a writeback register dummy placeholder.
3299 Inst.addOperand(MCOperand::CreateImm(0));
3300 // addr
3301 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3302 // pred
3303 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3304 return true;
3305}
3306
Jim Grosbach14605d12011-08-11 20:28:23 +00003307/// cvtStrdPre - Convert parsed operands to MCInst.
3308/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3309/// when they refer multiple MIOperands inside a single one.
3310bool ARMAsmParser::
3311cvtStrdPre(MCInst &Inst, unsigned Opcode,
3312 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3313 // Create a writeback register dummy placeholder.
3314 Inst.addOperand(MCOperand::CreateImm(0));
3315 // Rt, Rt2
3316 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3317 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3318 // addr
3319 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3320 // pred
3321 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3322 return true;
3323}
3324
Jim Grosbach623a4542011-08-10 22:42:16 +00003325/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3326/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3327/// when they refer multiple MIOperands inside a single one.
3328bool ARMAsmParser::
3329cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3330 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3331 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3332 // Create a writeback register dummy placeholder.
3333 Inst.addOperand(MCOperand::CreateImm(0));
3334 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3335 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3336 return true;
3337}
3338
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003339/// cvtThumbMultiple- Convert parsed operands to MCInst.
3340/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3341/// when they refer multiple MIOperands inside a single one.
3342bool ARMAsmParser::
3343cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3344 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3345 // The second source operand must be the same register as the destination
3346 // operand.
3347 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003348 (((ARMOperand*)Operands[3])->getReg() !=
3349 ((ARMOperand*)Operands[5])->getReg()) &&
3350 (((ARMOperand*)Operands[3])->getReg() !=
3351 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003352 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003353 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003354 return false;
3355 }
3356 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3357 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3358 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003359 // If we have a three-operand form, use that, else the second source operand
3360 // is just the destination operand again.
3361 if (Operands.size() == 6)
3362 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3363 else
3364 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003365 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3366
3367 return true;
3368}
Jim Grosbach623a4542011-08-10 22:42:16 +00003369
Jim Grosbach12431322011-10-24 22:16:58 +00003370bool ARMAsmParser::
3371cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3372 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3373 // Vd
3374 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3375 // Create a writeback register dummy placeholder.
3376 Inst.addOperand(MCOperand::CreateImm(0));
3377 // Vn
3378 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3379 // pred
3380 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3381 return true;
3382}
3383
3384bool ARMAsmParser::
3385cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3386 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3387 // Vd
3388 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3389 // Create a writeback register dummy placeholder.
3390 Inst.addOperand(MCOperand::CreateImm(0));
3391 // Vn
3392 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3393 // Vm
3394 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3395 // pred
3396 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3397 return true;
3398}
3399
Bill Wendlinge7176102010-11-06 22:36:58 +00003400/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003401/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003402bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003403parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003404 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003405 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003406 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003407 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003408 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003409
Sean Callanan18b83232010-01-19 21:44:56 +00003410 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003411 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003412 if (BaseRegNum == -1)
3413 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003414
Daniel Dunbar05710932011-01-18 05:34:17 +00003415 // The next token must either be a comma or a closing bracket.
3416 const AsmToken &Tok = Parser.getTok();
3417 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003418 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003419
Jim Grosbach7ce05792011-08-03 23:50:40 +00003420 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003421 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003422 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003423
Jim Grosbach7ce05792011-08-03 23:50:40 +00003424 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003425 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003426
Jim Grosbachfb12f352011-09-19 18:42:21 +00003427 // If there's a pre-indexing writeback marker, '!', just add it as a token
3428 // operand. It's rather odd, but syntactically valid.
3429 if (Parser.getTok().is(AsmToken::Exclaim)) {
3430 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3431 Parser.Lex(); // Eat the '!'.
3432 }
3433
Jim Grosbach7ce05792011-08-03 23:50:40 +00003434 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003435 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003436
Jim Grosbach7ce05792011-08-03 23:50:40 +00003437 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3438 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003439
Jim Grosbach57dcb852011-10-11 17:29:55 +00003440 // If we have a ':', it's an alignment specifier.
3441 if (Parser.getTok().is(AsmToken::Colon)) {
3442 Parser.Lex(); // Eat the ':'.
3443 E = Parser.getTok().getLoc();
3444
3445 const MCExpr *Expr;
3446 if (getParser().ParseExpression(Expr))
3447 return true;
3448
3449 // The expression has to be a constant. Memory references with relocations
3450 // don't come through here, as they use the <label> forms of the relevant
3451 // instructions.
3452 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3453 if (!CE)
3454 return Error (E, "constant expression expected");
3455
3456 unsigned Align = 0;
3457 switch (CE->getValue()) {
3458 default:
3459 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3460 case 64: Align = 8; break;
3461 case 128: Align = 16; break;
3462 case 256: Align = 32; break;
3463 }
3464
3465 // Now we should have the closing ']'
3466 E = Parser.getTok().getLoc();
3467 if (Parser.getTok().isNot(AsmToken::RBrac))
3468 return Error(E, "']' expected");
3469 Parser.Lex(); // Eat right bracket token.
3470
3471 // Don't worry about range checking the value here. That's handled by
3472 // the is*() predicates.
3473 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3474 ARM_AM::no_shift, 0, Align,
3475 false, S, E));
3476
3477 // If there's a pre-indexing writeback marker, '!', just add it as a token
3478 // operand.
3479 if (Parser.getTok().is(AsmToken::Exclaim)) {
3480 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3481 Parser.Lex(); // Eat the '!'.
3482 }
3483
3484 return false;
3485 }
3486
3487 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003488 // offset.
3489 if (Parser.getTok().is(AsmToken::Hash)) {
3490 Parser.Lex(); // Eat the '#'.
3491 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003492
Owen Anderson0da10cf2011-08-29 19:36:44 +00003493 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003494 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003495 if (getParser().ParseExpression(Offset))
3496 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003497
3498 // The expression has to be a constant. Memory references with relocations
3499 // don't come through here, as they use the <label> forms of the relevant
3500 // instructions.
3501 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3502 if (!CE)
3503 return Error (E, "constant expression expected");
3504
Owen Anderson0da10cf2011-08-29 19:36:44 +00003505 // If the constant was #-0, represent it as INT32_MIN.
3506 int32_t Val = CE->getValue();
3507 if (isNegative && Val == 0)
3508 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3509
Jim Grosbach7ce05792011-08-03 23:50:40 +00003510 // Now we should have the closing ']'
3511 E = Parser.getTok().getLoc();
3512 if (Parser.getTok().isNot(AsmToken::RBrac))
3513 return Error(E, "']' expected");
3514 Parser.Lex(); // Eat right bracket token.
3515
3516 // Don't worry about range checking the value here. That's handled by
3517 // the is*() predicates.
3518 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003519 ARM_AM::no_shift, 0, 0,
3520 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003521
3522 // If there's a pre-indexing writeback marker, '!', just add it as a token
3523 // operand.
3524 if (Parser.getTok().is(AsmToken::Exclaim)) {
3525 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3526 Parser.Lex(); // Eat the '!'.
3527 }
3528
3529 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003530 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003531
3532 // The register offset is optionally preceded by a '+' or '-'
3533 bool isNegative = false;
3534 if (Parser.getTok().is(AsmToken::Minus)) {
3535 isNegative = true;
3536 Parser.Lex(); // Eat the '-'.
3537 } else if (Parser.getTok().is(AsmToken::Plus)) {
3538 // Nothing to do.
3539 Parser.Lex(); // Eat the '+'.
3540 }
3541
3542 E = Parser.getTok().getLoc();
3543 int OffsetRegNum = tryParseRegister();
3544 if (OffsetRegNum == -1)
3545 return Error(E, "register expected");
3546
3547 // If there's a shift operator, handle it.
3548 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003549 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003550 if (Parser.getTok().is(AsmToken::Comma)) {
3551 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003552 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003553 return true;
3554 }
3555
3556 // Now we should have the closing ']'
3557 E = Parser.getTok().getLoc();
3558 if (Parser.getTok().isNot(AsmToken::RBrac))
3559 return Error(E, "']' expected");
3560 Parser.Lex(); // Eat right bracket token.
3561
3562 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003563 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003564 S, E));
3565
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003566 // If there's a pre-indexing writeback marker, '!', just add it as a token
3567 // operand.
3568 if (Parser.getTok().is(AsmToken::Exclaim)) {
3569 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3570 Parser.Lex(); // Eat the '!'.
3571 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003572
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003573 return false;
3574}
3575
Jim Grosbach7ce05792011-08-03 23:50:40 +00003576/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003577/// ( lsl | lsr | asr | ror ) , # shift_amount
3578/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003579/// return true if it parses a shift otherwise it returns false.
3580bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3581 unsigned &Amount) {
3582 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003583 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003584 if (Tok.isNot(AsmToken::Identifier))
3585 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003586 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003587 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003588 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003589 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003590 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003591 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003592 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003593 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003594 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003595 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003596 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003597 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003598 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003599 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003600
Jim Grosbach7ce05792011-08-03 23:50:40 +00003601 // rrx stands alone.
3602 Amount = 0;
3603 if (St != ARM_AM::rrx) {
3604 Loc = Parser.getTok().getLoc();
3605 // A '#' and a shift amount.
3606 const AsmToken &HashTok = Parser.getTok();
3607 if (HashTok.isNot(AsmToken::Hash))
3608 return Error(HashTok.getLoc(), "'#' expected");
3609 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003610
Jim Grosbach7ce05792011-08-03 23:50:40 +00003611 const MCExpr *Expr;
3612 if (getParser().ParseExpression(Expr))
3613 return true;
3614 // Range check the immediate.
3615 // lsl, ror: 0 <= imm <= 31
3616 // lsr, asr: 0 <= imm <= 32
3617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3618 if (!CE)
3619 return Error(Loc, "shift amount must be an immediate");
3620 int64_t Imm = CE->getValue();
3621 if (Imm < 0 ||
3622 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3623 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3624 return Error(Loc, "immediate shift value out of range");
3625 Amount = Imm;
3626 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003627
3628 return false;
3629}
3630
Jim Grosbach9d390362011-10-03 23:38:36 +00003631/// parseFPImm - A floating point immediate expression operand.
3632ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3633parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3634 SMLoc S = Parser.getTok().getLoc();
3635
3636 if (Parser.getTok().isNot(AsmToken::Hash))
3637 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003638
3639 // Disambiguate the VMOV forms that can accept an FP immediate.
3640 // vmov.f32 <sreg>, #imm
3641 // vmov.f64 <dreg>, #imm
3642 // vmov.f32 <dreg>, #imm @ vector f32x2
3643 // vmov.f32 <qreg>, #imm @ vector f32x4
3644 //
3645 // There are also the NEON VMOV instructions which expect an
3646 // integer constant. Make sure we don't try to parse an FPImm
3647 // for these:
3648 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3649 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3650 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3651 TyOp->getToken() != ".f64"))
3652 return MatchOperand_NoMatch;
3653
Jim Grosbach9d390362011-10-03 23:38:36 +00003654 Parser.Lex(); // Eat the '#'.
3655
3656 // Handle negation, as that still comes through as a separate token.
3657 bool isNegative = false;
3658 if (Parser.getTok().is(AsmToken::Minus)) {
3659 isNegative = true;
3660 Parser.Lex();
3661 }
3662 const AsmToken &Tok = Parser.getTok();
3663 if (Tok.is(AsmToken::Real)) {
3664 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3665 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3666 // If we had a '-' in front, toggle the sign bit.
3667 IntVal ^= (uint64_t)isNegative << 63;
3668 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3669 Parser.Lex(); // Eat the token.
3670 if (Val == -1) {
3671 TokError("floating point value out of range");
3672 return MatchOperand_ParseFail;
3673 }
3674 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3675 return MatchOperand_Success;
3676 }
3677 if (Tok.is(AsmToken::Integer)) {
3678 int64_t Val = Tok.getIntVal();
3679 Parser.Lex(); // Eat the token.
3680 if (Val > 255 || Val < 0) {
3681 TokError("encoded floating point value out of range");
3682 return MatchOperand_ParseFail;
3683 }
3684 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3685 return MatchOperand_Success;
3686 }
3687
3688 TokError("invalid floating point immediate");
3689 return MatchOperand_ParseFail;
3690}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003691/// Parse a arm instruction operand. For now this parses the operand regardless
3692/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003693bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003694 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003695 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003696
3697 // Check if the current operand has a custom associated parser, if so, try to
3698 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003699 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3700 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003701 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003702 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3703 // there was a match, but an error occurred, in which case, just return that
3704 // the operand parsing failed.
3705 if (ResTy == MatchOperand_ParseFail)
3706 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003707
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003708 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003709 default:
3710 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003711 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003712 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003713 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003714 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003715 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003716 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003717 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003718 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003719 else if (Res == -1) // irrecoverable error
3720 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003721 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3722 S = Parser.getTok().getLoc();
3723 Parser.Lex();
3724 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3725 return false;
3726 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003727
3728 // Fall though for the Identifier case that is not a register or a
3729 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003730 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003731 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003732 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3733 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003734 // This was not a register so parse other operands that start with an
3735 // identifier (like labels) as expressions and create them as immediates.
3736 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003737 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003738 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003739 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003740 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003741 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3742 return false;
3743 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003744 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003745 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003746 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003747 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003748 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003749 // #42 -> immediate.
3750 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003751 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003752 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003753 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003754 const MCExpr *ImmVal;
3755 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003756 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3758 if (!CE) {
3759 Error(S, "constant expression expected");
3760 return MatchOperand_ParseFail;
3761 }
3762 int32_t Val = CE->getValue();
3763 if (isNegative && Val == 0)
3764 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003765 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003766 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3767 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003768 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003769 case AsmToken::Colon: {
3770 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003771 // FIXME: Check it's an expression prefix,
3772 // e.g. (FOO - :lower16:BAR) isn't legal.
3773 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003774 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003775 return true;
3776
Evan Cheng75972122011-01-13 07:58:56 +00003777 const MCExpr *SubExprVal;
3778 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003779 return true;
3780
Evan Cheng75972122011-01-13 07:58:56 +00003781 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3782 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003783 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003784 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003785 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003786 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003787 }
3788}
3789
Jim Grosbach1355cf12011-07-26 17:10:22 +00003790// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003791// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003792bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003793 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003794
3795 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003796 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003797 Parser.Lex(); // Eat ':'
3798
3799 if (getLexer().isNot(AsmToken::Identifier)) {
3800 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3801 return true;
3802 }
3803
3804 StringRef IDVal = Parser.getTok().getIdentifier();
3805 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003806 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003807 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003808 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003809 } else {
3810 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3811 return true;
3812 }
3813 Parser.Lex();
3814
3815 if (getLexer().isNot(AsmToken::Colon)) {
3816 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3817 return true;
3818 }
3819 Parser.Lex(); // Eat the last ':'
3820 return false;
3821}
3822
Daniel Dunbar352e1482011-01-11 15:59:50 +00003823/// \brief Given a mnemonic, split out possible predication code and carry
3824/// setting letters to form a canonical mnemonic and flags.
3825//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003826// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003827// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003828StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003829 unsigned &PredicationCode,
3830 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003831 unsigned &ProcessorIMod,
3832 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003833 PredicationCode = ARMCC::AL;
3834 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003835 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003836
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003837 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003838 //
3839 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003840 if ((Mnemonic == "movs" && isThumb()) ||
3841 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3842 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3843 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3844 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3845 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3846 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3847 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003848 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003849
Jim Grosbach3f00e312011-07-11 17:09:57 +00003850 // First, split out any predication code. Ignore mnemonics we know aren't
3851 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003852 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003853 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003854 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003855 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003856 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3857 .Case("eq", ARMCC::EQ)
3858 .Case("ne", ARMCC::NE)
3859 .Case("hs", ARMCC::HS)
3860 .Case("cs", ARMCC::HS)
3861 .Case("lo", ARMCC::LO)
3862 .Case("cc", ARMCC::LO)
3863 .Case("mi", ARMCC::MI)
3864 .Case("pl", ARMCC::PL)
3865 .Case("vs", ARMCC::VS)
3866 .Case("vc", ARMCC::VC)
3867 .Case("hi", ARMCC::HI)
3868 .Case("ls", ARMCC::LS)
3869 .Case("ge", ARMCC::GE)
3870 .Case("lt", ARMCC::LT)
3871 .Case("gt", ARMCC::GT)
3872 .Case("le", ARMCC::LE)
3873 .Case("al", ARMCC::AL)
3874 .Default(~0U);
3875 if (CC != ~0U) {
3876 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3877 PredicationCode = CC;
3878 }
Bill Wendling52925b62010-10-29 23:50:21 +00003879 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003880
Daniel Dunbar352e1482011-01-11 15:59:50 +00003881 // Next, determine if we have a carry setting bit. We explicitly ignore all
3882 // the instructions we know end in 's'.
3883 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003884 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003885 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3886 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3887 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003888 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3889 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003890 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3891 CarrySetting = true;
3892 }
3893
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003894 // The "cps" instruction can have a interrupt mode operand which is glued into
3895 // the mnemonic. Check if this is the case, split it and parse the imod op
3896 if (Mnemonic.startswith("cps")) {
3897 // Split out any imod code.
3898 unsigned IMod =
3899 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3900 .Case("ie", ARM_PROC::IE)
3901 .Case("id", ARM_PROC::ID)
3902 .Default(~0U);
3903 if (IMod != ~0U) {
3904 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3905 ProcessorIMod = IMod;
3906 }
3907 }
3908
Jim Grosbach89df9962011-08-26 21:43:41 +00003909 // The "it" instruction has the condition mask on the end of the mnemonic.
3910 if (Mnemonic.startswith("it")) {
3911 ITMask = Mnemonic.slice(2, Mnemonic.size());
3912 Mnemonic = Mnemonic.slice(0, 2);
3913 }
3914
Daniel Dunbar352e1482011-01-11 15:59:50 +00003915 return Mnemonic;
3916}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003917
3918/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3919/// inclusion of carry set or predication code operands.
3920//
3921// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003922void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003923getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003924 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003925 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3926 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003927 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003928 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003929 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003930 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003931 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003932 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003933 Mnemonic == "mla" || Mnemonic == "smlal" ||
3934 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003935 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003936 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003937 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003938
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003939 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3940 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3941 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3942 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003943 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3944 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003945 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003946 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3947 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3948 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003949 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3950 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003951 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003952 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003953 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003954 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003955
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003956 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003957 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003958 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003959 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003960 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003961}
3962
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003963bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3964 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003965 // FIXME: This is all horribly hacky. We really need a better way to deal
3966 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003967
3968 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3969 // another does not. Specifically, the MOVW instruction does not. So we
3970 // special case it here and remove the defaulted (non-setting) cc_out
3971 // operand if that's the instruction we're trying to match.
3972 //
3973 // We do this as post-processing of the explicit operands rather than just
3974 // conditionally adding the cc_out in the first place because we need
3975 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003976 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003977 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3978 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3979 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3980 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003981
3982 // Register-register 'add' for thumb does not have a cc_out operand
3983 // when there are only two register operands.
3984 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3985 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3986 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3987 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3988 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003989 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003990 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3991 // have to check the immediate range here since Thumb2 has a variant
3992 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003993 if (((isThumb() && Mnemonic == "add") ||
3994 (isThumbTwo() && Mnemonic == "sub")) &&
3995 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003996 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3997 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3998 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003999 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4000 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4001 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004002 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004003 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4004 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004005 // selecting via the generic "add" mnemonic, so to know that we
4006 // should remove the cc_out operand, we have to explicitly check that
4007 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004008 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4009 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004010 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4011 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4012 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4013 // Nest conditions rather than one big 'if' statement for readability.
4014 //
4015 // If either register is a high reg, it's either one of the SP
4016 // variants (handled above) or a 32-bit encoding, so we just
4017 // check against T3.
4018 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4019 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4020 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4021 return false;
4022 // If both registers are low, we're in an IT block, and the immediate is
4023 // in range, we should use encoding T1 instead, which has a cc_out.
4024 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004025 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004026 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4027 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4028 return false;
4029
4030 // Otherwise, we use encoding T4, which does not have a cc_out
4031 // operand.
4032 return true;
4033 }
4034
Jim Grosbach64944f42011-09-14 21:00:40 +00004035 // The thumb2 multiply instruction doesn't have a CCOut register, so
4036 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4037 // use the 16-bit encoding or not.
4038 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4039 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4040 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4041 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4042 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4043 // If the registers aren't low regs, the destination reg isn't the
4044 // same as one of the source regs, or the cc_out operand is zero
4045 // outside of an IT block, we have to use the 32-bit encoding, so
4046 // remove the cc_out operand.
4047 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4048 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4049 !inITBlock() ||
4050 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4051 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4052 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4053 static_cast<ARMOperand*>(Operands[4])->getReg())))
4054 return true;
4055
4056
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004057
Jim Grosbachf69c8042011-08-24 21:42:27 +00004058 // Register-register 'add/sub' for thumb does not have a cc_out operand
4059 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4060 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4061 // right, this will result in better diagnostics (which operand is off)
4062 // anyway.
4063 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4064 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004065 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4066 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4067 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4068 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004069
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004070 return false;
4071}
4072
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004073/// Parse an arm instruction mnemonic followed by its operands.
4074bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4075 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4076 // Create the leading tokens for the mnemonic, split by '.' characters.
4077 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004078 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004079
Daniel Dunbar352e1482011-01-11 15:59:50 +00004080 // Split out the predication code and carry setting flag from the mnemonic.
4081 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004082 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004083 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004084 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004085 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004086 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004087
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004088 // In Thumb1, only the branch (B) instruction can be predicated.
4089 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4090 Parser.EatToEndOfStatement();
4091 return Error(NameLoc, "conditional execution not supported in Thumb1");
4092 }
4093
Jim Grosbachffa32252011-07-19 19:13:28 +00004094 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4095
Jim Grosbach89df9962011-08-26 21:43:41 +00004096 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4097 // is the mask as it will be for the IT encoding if the conditional
4098 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4099 // where the conditional bit0 is zero, the instruction post-processing
4100 // will adjust the mask accordingly.
4101 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004102 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4103 if (ITMask.size() > 3) {
4104 Parser.EatToEndOfStatement();
4105 return Error(Loc, "too many conditions on IT instruction");
4106 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004107 unsigned Mask = 8;
4108 for (unsigned i = ITMask.size(); i != 0; --i) {
4109 char pos = ITMask[i - 1];
4110 if (pos != 't' && pos != 'e') {
4111 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004112 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004113 }
4114 Mask >>= 1;
4115 if (ITMask[i - 1] == 't')
4116 Mask |= 8;
4117 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004118 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004119 }
4120
Jim Grosbachffa32252011-07-19 19:13:28 +00004121 // FIXME: This is all a pretty gross hack. We should automatically handle
4122 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004123
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004124 // Next, add the CCOut and ConditionCode operands, if needed.
4125 //
4126 // For mnemonics which can ever incorporate a carry setting bit or predication
4127 // code, our matching model involves us always generating CCOut and
4128 // ConditionCode operands to match the mnemonic "as written" and then we let
4129 // the matcher deal with finding the right instruction or generating an
4130 // appropriate error.
4131 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004132 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004133
Jim Grosbach33c16a22011-07-14 22:04:21 +00004134 // If we had a carry-set on an instruction that can't do that, issue an
4135 // error.
4136 if (!CanAcceptCarrySet && CarrySetting) {
4137 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004138 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004139 "' can not set flags, but 's' suffix specified");
4140 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004141 // If we had a predication code on an instruction that can't do that, issue an
4142 // error.
4143 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4144 Parser.EatToEndOfStatement();
4145 return Error(NameLoc, "instruction '" + Mnemonic +
4146 "' is not predicable, but condition code specified");
4147 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004148
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004149 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004150 if (CanAcceptCarrySet) {
4151 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004152 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004153 Loc));
4154 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004155
4156 // Add the predication code operand, if necessary.
4157 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004158 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4159 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004160 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004161 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004162 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004163
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004164 // Add the processor imod operand, if necessary.
4165 if (ProcessorIMod) {
4166 Operands.push_back(ARMOperand::CreateImm(
4167 MCConstantExpr::Create(ProcessorIMod, getContext()),
4168 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004169 }
4170
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004171 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004172 while (Next != StringRef::npos) {
4173 Start = Next;
4174 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004175 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004176
Jim Grosbach4d23e992011-08-24 22:19:48 +00004177 // For now, we're only parsing Thumb1 (for the most part), so
4178 // just ignore ".n" qualifiers. We'll use them to restrict
4179 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00004180 if (ExtraToken != ".n") {
4181 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4182 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4183 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004184 }
4185
4186 // Read the remaining operands.
4187 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004188 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004189 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004190 Parser.EatToEndOfStatement();
4191 return true;
4192 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004193
4194 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004195 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004196
4197 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004198 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004199 Parser.EatToEndOfStatement();
4200 return true;
4201 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004202 }
4203 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004204
Chris Lattnercbf8a982010-09-11 16:18:25 +00004205 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004206 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004207 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004208 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004209 }
Bill Wendling146018f2010-11-06 21:42:12 +00004210
Chris Lattner34e53142010-09-08 05:10:46 +00004211 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004212
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004213 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4214 // do and don't have a cc_out optional-def operand. With some spot-checks
4215 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004216 // parse and adjust accordingly before actually matching. We shouldn't ever
4217 // try to remove a cc_out operand that was explicitly set on the the
4218 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4219 // table driven matcher doesn't fit well with the ARM instruction set.
4220 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004221 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4222 Operands.erase(Operands.begin() + 1);
4223 delete Op;
4224 }
4225
Jim Grosbachcf121c32011-07-28 21:57:55 +00004226 // ARM mode 'blx' need special handling, as the register operand version
4227 // is predicable, but the label operand version is not. So, we can't rely
4228 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004229 // a k_CondCode operand in the list. If we're trying to match the label
4230 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004231 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4232 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4233 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4234 Operands.erase(Operands.begin() + 1);
4235 delete Op;
4236 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004237
4238 // The vector-compare-to-zero instructions have a literal token "#0" at
4239 // the end that comes to here as an immediate operand. Convert it to a
4240 // token to play nicely with the matcher.
4241 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4242 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4243 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4244 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4245 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4246 if (CE && CE->getValue() == 0) {
4247 Operands.erase(Operands.begin() + 5);
4248 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4249 delete Op;
4250 }
4251 }
Jim Grosbach68259142011-10-03 22:30:24 +00004252 // VCMP{E} does the same thing, but with a different operand count.
4253 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4254 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4255 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4256 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4257 if (CE && CE->getValue() == 0) {
4258 Operands.erase(Operands.begin() + 4);
4259 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4260 delete Op;
4261 }
4262 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004263 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4264 // end. Convert it to a token here.
4265 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4266 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4267 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4268 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4269 if (CE && CE->getValue() == 0) {
4270 Operands.erase(Operands.begin() + 5);
4271 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4272 delete Op;
4273 }
4274 }
4275
Chris Lattner98986712010-01-14 22:21:20 +00004276 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004277}
4278
Jim Grosbach189610f2011-07-26 18:25:39 +00004279// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004280
4281// return 'true' if register list contains non-low GPR registers,
4282// 'false' otherwise. If Reg is in the register list or is HiReg, set
4283// 'containsReg' to true.
4284static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4285 unsigned HiReg, bool &containsReg) {
4286 containsReg = false;
4287 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4288 unsigned OpReg = Inst.getOperand(i).getReg();
4289 if (OpReg == Reg)
4290 containsReg = true;
4291 // Anything other than a low register isn't legal here.
4292 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4293 return true;
4294 }
4295 return false;
4296}
4297
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004298// Check if the specified regisgter is in the register list of the inst,
4299// starting at the indicated operand number.
4300static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4301 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4302 unsigned OpReg = Inst.getOperand(i).getReg();
4303 if (OpReg == Reg)
4304 return true;
4305 }
4306 return false;
4307}
4308
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004309// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4310// the ARMInsts array) instead. Getting that here requires awkward
4311// API changes, though. Better way?
4312namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004313extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004314}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004315static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004316 return ARMInsts[Opcode];
4317}
4318
Jim Grosbach189610f2011-07-26 18:25:39 +00004319// FIXME: We would really like to be able to tablegen'erate this.
4320bool ARMAsmParser::
4321validateInstruction(MCInst &Inst,
4322 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004323 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004324 SMLoc Loc = Operands[0]->getStartLoc();
4325 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004326 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4327 // being allowed in IT blocks, but not being predicable. It just always
4328 // executes.
4329 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004330 unsigned bit = 1;
4331 if (ITState.FirstCond)
4332 ITState.FirstCond = false;
4333 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004334 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004335 // The instruction must be predicable.
4336 if (!MCID.isPredicable())
4337 return Error(Loc, "instructions in IT block must be predicable");
4338 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4339 unsigned ITCond = bit ? ITState.Cond :
4340 ARMCC::getOppositeCondition(ITState.Cond);
4341 if (Cond != ITCond) {
4342 // Find the condition code Operand to get its SMLoc information.
4343 SMLoc CondLoc;
4344 for (unsigned i = 1; i < Operands.size(); ++i)
4345 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4346 CondLoc = Operands[i]->getStartLoc();
4347 return Error(CondLoc, "incorrect condition in IT block; got '" +
4348 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4349 "', but expected '" +
4350 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4351 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004352 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004353 } else if (isThumbTwo() && MCID.isPredicable() &&
4354 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004355 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4356 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004357 return Error(Loc, "predicated instructions must be in IT block");
4358
Jim Grosbach189610f2011-07-26 18:25:39 +00004359 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004360 case ARM::LDRD:
4361 case ARM::LDRD_PRE:
4362 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004363 case ARM::LDREXD: {
4364 // Rt2 must be Rt + 1.
4365 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4366 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4367 if (Rt2 != Rt + 1)
4368 return Error(Operands[3]->getStartLoc(),
4369 "destination operands must be sequential");
4370 return false;
4371 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004372 case ARM::STRD: {
4373 // Rt2 must be Rt + 1.
4374 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4375 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4376 if (Rt2 != Rt + 1)
4377 return Error(Operands[3]->getStartLoc(),
4378 "source operands must be sequential");
4379 return false;
4380 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004381 case ARM::STRD_PRE:
4382 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004383 case ARM::STREXD: {
4384 // Rt2 must be Rt + 1.
4385 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4386 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4387 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004388 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004389 "source operands must be sequential");
4390 return false;
4391 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004392 case ARM::SBFX:
4393 case ARM::UBFX: {
4394 // width must be in range [1, 32-lsb]
4395 unsigned lsb = Inst.getOperand(2).getImm();
4396 unsigned widthm1 = Inst.getOperand(3).getImm();
4397 if (widthm1 >= 32 - lsb)
4398 return Error(Operands[5]->getStartLoc(),
4399 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004400 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004401 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004402 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004403 // If we're parsing Thumb2, the .w variant is available and handles
4404 // most cases that are normally illegal for a Thumb1 LDM
4405 // instruction. We'll make the transformation in processInstruction()
4406 // if necessary.
4407 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004408 // Thumb LDM instructions are writeback iff the base register is not
4409 // in the register list.
4410 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004411 bool hasWritebackToken =
4412 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4413 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004414 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004415 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004416 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4417 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004418 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004419 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004420 return Error(Operands[2]->getStartLoc(),
4421 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004422 // If we should not have writeback, there must not be a '!'. This is
4423 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004424 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004425 return Error(Operands[3]->getStartLoc(),
4426 "writeback operator '!' not allowed when base register "
4427 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004428
4429 break;
4430 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004431 case ARM::t2LDMIA_UPD: {
4432 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4433 return Error(Operands[4]->getStartLoc(),
4434 "writeback operator '!' not allowed when base register "
4435 "in register list");
4436 break;
4437 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004438 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004439 bool listContainsBase;
4440 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4441 return Error(Operands[2]->getStartLoc(),
4442 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004443 break;
4444 }
4445 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004446 bool listContainsBase;
4447 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4448 return Error(Operands[2]->getStartLoc(),
4449 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004450 break;
4451 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004452 case ARM::tSTMIA_UPD: {
4453 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004454 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004455 return Error(Operands[4]->getStartLoc(),
4456 "registers must be in range r0-r7");
4457 break;
4458 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004459 }
4460
4461 return false;
4462}
4463
Jim Grosbachf8fce712011-08-11 17:35:48 +00004464void ARMAsmParser::
4465processInstruction(MCInst &Inst,
4466 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4467 switch (Inst.getOpcode()) {
4468 case ARM::LDMIA_UPD:
4469 // If this is a load of a single register via a 'pop', then we should use
4470 // a post-indexed LDR instruction instead, per the ARM ARM.
4471 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4472 Inst.getNumOperands() == 5) {
4473 MCInst TmpInst;
4474 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4475 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4476 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4477 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4478 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4479 TmpInst.addOperand(MCOperand::CreateImm(4));
4480 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4481 TmpInst.addOperand(Inst.getOperand(3));
4482 Inst = TmpInst;
4483 }
4484 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004485 case ARM::STMDB_UPD:
4486 // If this is a store of a single register via a 'push', then we should use
4487 // a pre-indexed STR instruction instead, per the ARM ARM.
4488 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4489 Inst.getNumOperands() == 5) {
4490 MCInst TmpInst;
4491 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4492 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4493 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4494 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4495 TmpInst.addOperand(MCOperand::CreateImm(-4));
4496 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4497 TmpInst.addOperand(Inst.getOperand(3));
4498 Inst = TmpInst;
4499 }
4500 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004501 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004502 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4503 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4504 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4505 // to encoding T1 if <Rd> is omitted."
4506 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004507 Inst.setOpcode(ARM::tADDi3);
4508 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004509 case ARM::tSUBi8:
4510 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4511 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4512 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4513 // to encoding T1 if <Rd> is omitted."
4514 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4515 Inst.setOpcode(ARM::tSUBi3);
4516 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004517 case ARM::tB:
4518 // A Thumb conditional branch outside of an IT block is a tBcc.
4519 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4520 Inst.setOpcode(ARM::tBcc);
4521 break;
4522 case ARM::t2B:
4523 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4524 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4525 Inst.setOpcode(ARM::t2Bcc);
4526 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004527 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004528 // If the conditional is AL or we're in an IT block, we really want t2B.
4529 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004530 Inst.setOpcode(ARM::t2B);
4531 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004532 case ARM::tBcc:
4533 // If the conditional is AL, we really want tB.
4534 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4535 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004536 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004537 case ARM::tLDMIA: {
4538 // If the register list contains any high registers, or if the writeback
4539 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4540 // instead if we're in Thumb2. Otherwise, this should have generated
4541 // an error in validateInstruction().
4542 unsigned Rn = Inst.getOperand(0).getReg();
4543 bool hasWritebackToken =
4544 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4545 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4546 bool listContainsBase;
4547 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4548 (!listContainsBase && !hasWritebackToken) ||
4549 (listContainsBase && hasWritebackToken)) {
4550 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4551 assert (isThumbTwo());
4552 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4553 // If we're switching to the updating version, we need to insert
4554 // the writeback tied operand.
4555 if (hasWritebackToken)
4556 Inst.insert(Inst.begin(),
4557 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4558 }
4559 break;
4560 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004561 case ARM::tSTMIA_UPD: {
4562 // If the register list contains any high registers, we need to use
4563 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4564 // should have generated an error in validateInstruction().
4565 unsigned Rn = Inst.getOperand(0).getReg();
4566 bool listContainsBase;
4567 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4568 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4569 assert (isThumbTwo());
4570 Inst.setOpcode(ARM::t2STMIA_UPD);
4571 }
4572 break;
4573 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004574 case ARM::t2MOVi: {
4575 // If we can use the 16-bit encoding and the user didn't explicitly
4576 // request the 32-bit variant, transform it here.
4577 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4578 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004579 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4580 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4581 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004582 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4583 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4584 // The operands aren't in the same order for tMOVi8...
4585 MCInst TmpInst;
4586 TmpInst.setOpcode(ARM::tMOVi8);
4587 TmpInst.addOperand(Inst.getOperand(0));
4588 TmpInst.addOperand(Inst.getOperand(4));
4589 TmpInst.addOperand(Inst.getOperand(1));
4590 TmpInst.addOperand(Inst.getOperand(2));
4591 TmpInst.addOperand(Inst.getOperand(3));
4592 Inst = TmpInst;
4593 }
4594 break;
4595 }
4596 case ARM::t2MOVr: {
4597 // If we can use the 16-bit encoding and the user didn't explicitly
4598 // request the 32-bit variant, transform it here.
4599 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4600 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4601 Inst.getOperand(2).getImm() == ARMCC::AL &&
4602 Inst.getOperand(4).getReg() == ARM::CPSR &&
4603 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4604 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4605 // The operands aren't the same for tMOV[S]r... (no cc_out)
4606 MCInst TmpInst;
4607 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4608 TmpInst.addOperand(Inst.getOperand(0));
4609 TmpInst.addOperand(Inst.getOperand(1));
4610 TmpInst.addOperand(Inst.getOperand(2));
4611 TmpInst.addOperand(Inst.getOperand(3));
4612 Inst = TmpInst;
4613 }
4614 break;
4615 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004616 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004617 case ARM::t2SXTB:
4618 case ARM::t2UXTH:
4619 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004620 // If we can use the 16-bit encoding and the user didn't explicitly
4621 // request the 32-bit variant, transform it here.
4622 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4623 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4624 Inst.getOperand(2).getImm() == 0 &&
4625 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4626 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004627 unsigned NewOpc;
4628 switch (Inst.getOpcode()) {
4629 default: llvm_unreachable("Illegal opcode!");
4630 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4631 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4632 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4633 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4634 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004635 // The operands aren't the same for thumb1 (no rotate operand).
4636 MCInst TmpInst;
4637 TmpInst.setOpcode(NewOpc);
4638 TmpInst.addOperand(Inst.getOperand(0));
4639 TmpInst.addOperand(Inst.getOperand(1));
4640 TmpInst.addOperand(Inst.getOperand(3));
4641 TmpInst.addOperand(Inst.getOperand(4));
4642 Inst = TmpInst;
4643 }
4644 break;
4645 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004646 case ARM::t2IT: {
4647 // The mask bits for all but the first condition are represented as
4648 // the low bit of the condition code value implies 't'. We currently
4649 // always have 1 implies 't', so XOR toggle the bits if the low bit
4650 // of the condition code is zero. The encoding also expects the low
4651 // bit of the condition to be encoded as bit 4 of the mask operand,
4652 // so mask that in if needed
4653 MCOperand &MO = Inst.getOperand(1);
4654 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004655 unsigned OrigMask = Mask;
4656 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004657 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004658 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4659 for (unsigned i = 3; i != TZ; --i)
4660 Mask ^= 1 << i;
4661 } else
4662 Mask |= 0x10;
4663 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004664
4665 // Set up the IT block state according to the IT instruction we just
4666 // matched.
4667 assert(!inITBlock() && "nested IT blocks?!");
4668 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4669 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4670 ITState.CurPosition = 0;
4671 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004672 break;
4673 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004674 }
4675}
4676
Jim Grosbach47a0d522011-08-16 20:45:50 +00004677unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4678 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4679 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004680 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004681 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004682 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4683 assert(MCID.hasOptionalDef() &&
4684 "optionally flag setting instruction missing optional def operand");
4685 assert(MCID.NumOperands == Inst.getNumOperands() &&
4686 "operand count mismatch!");
4687 // Find the optional-def operand (cc_out).
4688 unsigned OpNo;
4689 for (OpNo = 0;
4690 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4691 ++OpNo)
4692 ;
4693 // If we're parsing Thumb1, reject it completely.
4694 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4695 return Match_MnemonicFail;
4696 // If we're parsing Thumb2, which form is legal depends on whether we're
4697 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004698 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4699 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004700 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004701 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4702 inITBlock())
4703 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004704 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004705 // Some high-register supporting Thumb1 encodings only allow both registers
4706 // to be from r0-r7 when in Thumb2.
4707 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4708 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4709 isARMLowRegister(Inst.getOperand(2).getReg()))
4710 return Match_RequiresThumb2;
4711 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004712 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004713 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4714 isARMLowRegister(Inst.getOperand(1).getReg()))
4715 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004716 return Match_Success;
4717}
4718
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004719bool ARMAsmParser::
4720MatchAndEmitInstruction(SMLoc IDLoc,
4721 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4722 MCStreamer &Out) {
4723 MCInst Inst;
4724 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004725 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004726 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004727 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004728 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004729 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004730 // Context sensitive operand constraints aren't handled by the matcher,
4731 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004732 if (validateInstruction(Inst, Operands)) {
4733 // Still progress the IT block, otherwise one wrong condition causes
4734 // nasty cascading errors.
4735 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004736 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004737 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004738
Jim Grosbachf8fce712011-08-11 17:35:48 +00004739 // Some instructions need post-processing to, for example, tweak which
4740 // encoding is selected.
4741 processInstruction(Inst, Operands);
4742
Jim Grosbacha1109882011-09-02 23:22:08 +00004743 // Only move forward at the very end so that everything in validate
4744 // and process gets a consistent answer about whether we're in an IT
4745 // block.
4746 forwardITPosition();
4747
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004748 Out.EmitInstruction(Inst);
4749 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004750 case Match_MissingFeature:
4751 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4752 return true;
4753 case Match_InvalidOperand: {
4754 SMLoc ErrorLoc = IDLoc;
4755 if (ErrorInfo != ~0U) {
4756 if (ErrorInfo >= Operands.size())
4757 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004758
Chris Lattnere73d4f82010-10-28 21:41:58 +00004759 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4760 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4761 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004762
Chris Lattnere73d4f82010-10-28 21:41:58 +00004763 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004764 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004765 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004766 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004767 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004768 // The converter function will have already emited a diagnostic.
4769 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004770 case Match_RequiresNotITBlock:
4771 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004772 case Match_RequiresITBlock:
4773 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004774 case Match_RequiresV6:
4775 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4776 case Match_RequiresThumb2:
4777 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004778 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004779
Eric Christopherc223e2b2010-10-29 09:26:59 +00004780 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004781 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004782}
4783
Jim Grosbach1355cf12011-07-26 17:10:22 +00004784/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004785bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4786 StringRef IDVal = DirectiveID.getIdentifier();
4787 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004788 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004789 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004790 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004791 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004792 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004793 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004794 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004795 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004796 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004797 return true;
4798}
4799
Jim Grosbach1355cf12011-07-26 17:10:22 +00004800/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004801/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004802bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004803 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4804 for (;;) {
4805 const MCExpr *Value;
4806 if (getParser().ParseExpression(Value))
4807 return true;
4808
Chris Lattneraaec2052010-01-19 19:46:13 +00004809 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004810
4811 if (getLexer().is(AsmToken::EndOfStatement))
4812 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004813
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004814 // FIXME: Improve diagnostic.
4815 if (getLexer().isNot(AsmToken::Comma))
4816 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004817 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004818 }
4819 }
4820
Sean Callananb9a25b72010-01-19 20:27:46 +00004821 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004822 return false;
4823}
4824
Jim Grosbach1355cf12011-07-26 17:10:22 +00004825/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004826/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004827bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004828 if (getLexer().isNot(AsmToken::EndOfStatement))
4829 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004830 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004831
4832 // TODO: set thumb mode
4833 // TODO: tell the MC streamer the mode
4834 // getParser().getStreamer().Emit???();
4835 return false;
4836}
4837
Jim Grosbach1355cf12011-07-26 17:10:22 +00004838/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004839/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004840bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004841 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4842 bool isMachO = MAI.hasSubsectionsViaSymbols();
4843 StringRef Name;
4844
4845 // Darwin asm has function name after .thumb_func direction
4846 // ELF doesn't
4847 if (isMachO) {
4848 const AsmToken &Tok = Parser.getTok();
4849 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4850 return Error(L, "unexpected token in .thumb_func directive");
4851 Name = Tok.getString();
4852 Parser.Lex(); // Consume the identifier token.
4853 }
4854
Kevin Enderby515d5092009-10-15 20:48:48 +00004855 if (getLexer().isNot(AsmToken::EndOfStatement))
4856 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004857 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004858
Rafael Espindola64695402011-05-16 16:17:21 +00004859 // FIXME: assuming function name will be the line following .thumb_func
4860 if (!isMachO) {
4861 Name = Parser.getTok().getString();
4862 }
4863
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004864 // Mark symbol as a thumb symbol.
4865 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4866 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004867 return false;
4868}
4869
Jim Grosbach1355cf12011-07-26 17:10:22 +00004870/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004871/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004872bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004873 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004874 if (Tok.isNot(AsmToken::Identifier))
4875 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004876 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004877 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004878 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004879 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004880 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004881 else
4882 return Error(L, "unrecognized syntax mode in .syntax directive");
4883
4884 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004885 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004886 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004887
4888 // TODO tell the MC streamer the mode
4889 // getParser().getStreamer().Emit???();
4890 return false;
4891}
4892
Jim Grosbach1355cf12011-07-26 17:10:22 +00004893/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004894/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004895bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004896 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004897 if (Tok.isNot(AsmToken::Integer))
4898 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004899 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004900 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004901 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004902 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004903 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004904 else
4905 return Error(L, "invalid operand to .code directive");
4906
4907 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004908 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004909 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004910
Evan Cheng32869202011-07-08 22:36:29 +00004911 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004912 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004913 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004914 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004915 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004916 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004917 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004918 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004919 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004920
Kevin Enderby515d5092009-10-15 20:48:48 +00004921 return false;
4922}
4923
Sean Callanan90b70972010-04-07 20:29:34 +00004924extern "C" void LLVMInitializeARMAsmLexer();
4925
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004926/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004927extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004928 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4929 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004930 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004931}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004932
Chris Lattner0692ee62010-09-06 19:11:01 +00004933#define GET_REGISTER_MATCHER
4934#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004935#include "ARMGenAsmMatcher.inc"