blob: 03fba5aee98390bffd05ba24c2aca7e0d65eece6 [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 Grosbache70ec842011-10-28 22:50:54 +0000660 bool isARMSOImmNot() const {
661 if (Kind != k_Immediate)
662 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::getSOImmVal(~Value) != -1;
667 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000668 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000669 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000670 return false;
671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return ARM_AM::getT2SOImmVal(Value) != -1;
675 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000676 bool isT2SOImmNot() const {
677 if (Kind != k_Immediate)
678 return false;
679 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
680 if (!CE) return false;
681 int64_t Value = CE->getValue();
682 return ARM_AM::getT2SOImmVal(~Value) != -1;
683 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000684 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000685 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000686 return false;
687 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
688 if (!CE) return false;
689 int64_t Value = CE->getValue();
690 return Value == 1 || Value == 0;
691 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000692 bool isReg() const { return Kind == k_Register; }
693 bool isRegList() const { return Kind == k_RegisterList; }
694 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
695 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
696 bool isToken() const { return Kind == k_Token; }
697 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
698 bool isMemory() const { return Kind == k_Memory; }
699 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
700 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
701 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
702 bool isRotImm() const { return Kind == k_RotateImmediate; }
703 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
704 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000705 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000706 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000707 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000708 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000709 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000710 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000711 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000712 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
713 (alignOK || Memory.Alignment == 0);
714 }
715 bool isAlignedMemory() const {
716 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000717 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000718 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000719 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000720 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000721 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000722 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000723 if (!Memory.OffsetImm) return true;
724 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000725 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000726 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000727 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000728 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000729 return false;
730 // Immediate offset in range [-4095, 4095].
731 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
732 if (!CE) return false;
733 int64_t Val = CE->getValue();
734 return Val > -4096 && Val < 4096;
735 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000736 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000737 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000738 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000739 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000740 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000741 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000742 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000743 if (!Memory.OffsetImm) return true;
744 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000745 return Val > -256 && Val < 256;
746 }
747 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000748 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000749 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000750 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000751 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
752 // Immediate offset in range [-255, 255].
753 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
754 if (!CE) return false;
755 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000756 // Special case, #-0 is INT32_MIN.
757 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000758 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000759 bool isAddrMode5() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000760 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000761 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000762 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000763 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000764 if (!Memory.OffsetImm) return true;
765 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000766 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
767 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000768 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000769 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000770 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000771 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000772 return false;
773 return true;
774 }
775 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000776 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000777 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
778 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000779 return false;
780 return true;
781 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000782 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000783 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000784 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000785 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000786 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000787 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000788 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
789 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000790 return false;
791 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000792 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000793 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000794 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000795 return false;
796 return true;
797 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000798 bool isMemThumbRR() const {
799 // Thumb reg+reg addressing is simple. Just two registers, a base and
800 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000801 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000802 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000803 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000804 return isARMLowRegister(Memory.BaseRegNum) &&
805 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000806 }
807 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000808 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000809 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000810 return false;
811 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000812 if (!Memory.OffsetImm) return true;
813 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000814 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
815 }
Jim Grosbach38466302011-08-19 18:55:51 +0000816 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000817 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000818 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000819 return false;
820 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000821 if (!Memory.OffsetImm) return true;
822 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000823 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
824 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000825 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000826 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000827 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000828 return false;
829 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000830 if (!Memory.OffsetImm) return true;
831 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000832 return Val >= 0 && Val <= 31;
833 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000834 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000835 if (!isMemory() || Memory.OffsetRegNum != 0 ||
836 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000837 return false;
838 // Immediate offset, 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 Grosbachecd85892011-08-19 18:13:48 +0000841 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000842 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000843 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000844 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000845 return false;
846 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000847 if (!Memory.OffsetImm) return true;
848 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000849 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
850 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000851 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000852 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000853 return false;
854 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000857 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
858 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000859 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000861 return false;
862 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000865 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000866 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000867 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000869 return false;
870 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000873 return Val >= 0 && Val < 256;
874 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000875 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000877 return false;
878 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000881 return Val > -256 && Val < 0;
882 }
883 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000885 return false;
886 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000889 return (Val >= 0 && Val < 4096);
890 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000891 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000892 // If we have an immediate that's not a constant, treat it as a label
893 // reference needing a fixup. If it is a constant, it's something else
894 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000895 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000896 return true;
897
Jim Grosbach57dcb852011-10-11 17:29:55 +0000898 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000899 return false;
900 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000901 if (!Memory.OffsetImm) return true;
902 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000903 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000904 }
905 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000906 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000907 return false;
908 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
909 if (!CE) return false;
910 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000911 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000912 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000913 bool isPostIdxImm8s4() const {
914 if (Kind != k_Immediate)
915 return false;
916 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
917 if (!CE) return false;
918 int64_t Val = CE->getValue();
919 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
920 (Val == INT32_MIN);
921 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000922
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000923 bool isMSRMask() const { return Kind == k_MSRMask; }
924 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000925
Jim Grosbach0e387b22011-10-17 22:26:03 +0000926 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000927 bool isVecListOneD() const {
928 if (Kind != k_VectorList) return false;
929 return VectorList.Count == 1;
930 }
931
Jim Grosbach280dfad2011-10-21 18:54:25 +0000932 bool isVecListTwoD() const {
933 if (Kind != k_VectorList) return false;
934 return VectorList.Count == 2;
935 }
936
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000937 bool isVecListThreeD() const {
938 if (Kind != k_VectorList) return false;
939 return VectorList.Count == 3;
940 }
941
Jim Grosbachb6310312011-10-21 20:35:01 +0000942 bool isVecListFourD() const {
943 if (Kind != k_VectorList) return false;
944 return VectorList.Count == 4;
945 }
946
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000947 bool isVecListTwoQ() const {
948 if (Kind != k_VectorList) return false;
949 //FIXME: We haven't taught the parser to handle by-two register lists
950 // yet, so don't pretend to know one.
951 return VectorList.Count == 2 && false;
952 }
953
Jim Grosbach460a9052011-10-07 23:56:00 +0000954 bool isVectorIndex8() const {
955 if (Kind != k_VectorIndex) return false;
956 return VectorIndex.Val < 8;
957 }
958 bool isVectorIndex16() const {
959 if (Kind != k_VectorIndex) return false;
960 return VectorIndex.Val < 4;
961 }
962 bool isVectorIndex32() const {
963 if (Kind != k_VectorIndex) return false;
964 return VectorIndex.Val < 2;
965 }
966
Jim Grosbach0e387b22011-10-17 22:26:03 +0000967 bool isNEONi8splat() const {
968 if (Kind != k_Immediate)
969 return false;
970 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
971 // Must be a constant.
972 if (!CE) return false;
973 int64_t Value = CE->getValue();
974 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
975 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000976 return Value >= 0 && Value < 256;
977 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000978
Jim Grosbachea461102011-10-17 23:09:09 +0000979 bool isNEONi16splat() const {
980 if (Kind != k_Immediate)
981 return false;
982 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
983 // Must be a constant.
984 if (!CE) return false;
985 int64_t Value = CE->getValue();
986 // i16 value in the range [0,255] or [0x0100, 0xff00]
987 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
988 }
989
Jim Grosbach6248a542011-10-18 00:22:00 +0000990 bool isNEONi32splat() const {
991 if (Kind != k_Immediate)
992 return false;
993 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
994 // Must be a constant.
995 if (!CE) return false;
996 int64_t Value = CE->getValue();
997 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
998 return (Value >= 0 && Value < 256) ||
999 (Value >= 0x0100 && Value <= 0xff00) ||
1000 (Value >= 0x010000 && Value <= 0xff0000) ||
1001 (Value >= 0x01000000 && Value <= 0xff000000);
1002 }
1003
1004 bool isNEONi32vmov() const {
1005 if (Kind != k_Immediate)
1006 return false;
1007 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1008 // Must be a constant.
1009 if (!CE) return false;
1010 int64_t Value = CE->getValue();
1011 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1012 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1013 return (Value >= 0 && Value < 256) ||
1014 (Value >= 0x0100 && Value <= 0xff00) ||
1015 (Value >= 0x010000 && Value <= 0xff0000) ||
1016 (Value >= 0x01000000 && Value <= 0xff000000) ||
1017 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1018 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1019 }
1020
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001021 bool isNEONi64splat() const {
1022 if (Kind != k_Immediate)
1023 return false;
1024 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1025 // Must be a constant.
1026 if (!CE) return false;
1027 uint64_t Value = CE->getValue();
1028 // i64 value with each byte being either 0 or 0xff.
1029 for (unsigned i = 0; i < 8; ++i)
1030 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1031 return true;
1032 }
1033
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001034 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001035 // Add as immediates when possible. Null MCExpr = 0.
1036 if (Expr == 0)
1037 Inst.addOperand(MCOperand::CreateImm(0));
1038 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001039 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1040 else
1041 Inst.addOperand(MCOperand::CreateExpr(Expr));
1042 }
1043
Daniel Dunbar8462b302010-08-11 06:36:53 +00001044 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001045 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001046 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001047 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1048 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001049 }
1050
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001051 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1052 assert(N == 1 && "Invalid number of operands!");
1053 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1054 }
1055
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001056 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1057 assert(N == 1 && "Invalid number of operands!");
1058 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1059 }
1060
1061 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1062 assert(N == 1 && "Invalid number of operands!");
1063 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1064 }
1065
Jim Grosbach89df9962011-08-26 21:43:41 +00001066 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1067 assert(N == 1 && "Invalid number of operands!");
1068 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1069 }
1070
1071 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1072 assert(N == 1 && "Invalid number of operands!");
1073 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1074 }
1075
Jim Grosbachd67641b2010-12-06 18:21:12 +00001076 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1077 assert(N == 1 && "Invalid number of operands!");
1078 Inst.addOperand(MCOperand::CreateReg(getReg()));
1079 }
1080
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001081 void addRegOperands(MCInst &Inst, unsigned N) const {
1082 assert(N == 1 && "Invalid number of operands!");
1083 Inst.addOperand(MCOperand::CreateReg(getReg()));
1084 }
1085
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001086 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001087 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001088 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1089 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1090 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001091 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001092 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001093 }
1094
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001095 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001096 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001097 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1098 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001099 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001100 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001101 }
1102
Jim Grosbach580f4a92011-07-25 22:20:28 +00001103 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001104 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001105 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1106 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001107 }
1108
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001109 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001110 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001111 const SmallVectorImpl<unsigned> &RegList = getRegList();
1112 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001113 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1114 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001115 }
1116
Bill Wendling0f630752010-11-17 04:32:08 +00001117 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1118 addRegListOperands(Inst, N);
1119 }
1120
1121 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1122 addRegListOperands(Inst, N);
1123 }
1124
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001125 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1126 assert(N == 1 && "Invalid number of operands!");
1127 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1128 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1129 }
1130
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001131 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1132 assert(N == 1 && "Invalid number of operands!");
1133 // Munge the lsb/width into a bitfield mask.
1134 unsigned lsb = Bitfield.LSB;
1135 unsigned width = Bitfield.Width;
1136 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1137 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1138 (32 - (lsb + width)));
1139 Inst.addOperand(MCOperand::CreateImm(Mask));
1140 }
1141
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001142 void addImmOperands(MCInst &Inst, unsigned N) const {
1143 assert(N == 1 && "Invalid number of operands!");
1144 addExpr(Inst, getImm());
1145 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001146
Jim Grosbach9d390362011-10-03 23:38:36 +00001147 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1148 assert(N == 1 && "Invalid number of operands!");
1149 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1150 }
1151
Jim Grosbacha77295d2011-09-08 22:07:06 +00001152 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
1154 // FIXME: We really want to scale the value here, but the LDRD/STRD
1155 // instruction don't encode operands that way yet.
1156 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1157 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1158 }
1159
Jim Grosbach72f39f82011-08-24 21:22:15 +00001160 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 // The immediate is scaled by four in the encoding and is stored
1163 // in the MCInst as such. Lop off the low two bits here.
1164 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1165 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1166 }
1167
1168 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
1170 // The immediate is scaled by four in the encoding and is stored
1171 // in the MCInst as such. Lop off the low two bits here.
1172 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1173 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1174 }
1175
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001176 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
1178 addExpr(Inst, getImm());
1179 }
1180
Jim Grosbach83ab0702011-07-13 22:01:08 +00001181 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1182 assert(N == 1 && "Invalid number of operands!");
1183 addExpr(Inst, getImm());
1184 }
1185
1186 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188 addExpr(Inst, getImm());
1189 }
1190
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001191 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1192 assert(N == 1 && "Invalid number of operands!");
1193 addExpr(Inst, getImm());
1194 }
1195
Jim Grosbachf4943352011-07-25 23:09:14 +00001196 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
1198 // The constant encodes as the immediate-1, and we store in the instruction
1199 // the bits as encoded, so subtract off one here.
1200 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1201 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1202 }
1203
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001204 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1205 assert(N == 1 && "Invalid number of operands!");
1206 // The constant encodes as the immediate-1, and we store in the instruction
1207 // the bits as encoded, so subtract off one here.
1208 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1209 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1210 }
1211
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001212 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1213 assert(N == 1 && "Invalid number of operands!");
1214 addExpr(Inst, getImm());
1215 }
1216
Jim Grosbachffa32252011-07-19 19:13:28 +00001217 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
1219 addExpr(Inst, getImm());
1220 }
1221
Jim Grosbached838482011-07-26 16:24:27 +00001222 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1223 assert(N == 1 && "Invalid number of operands!");
1224 addExpr(Inst, getImm());
1225 }
1226
Jim Grosbach70939ee2011-08-17 21:51:27 +00001227 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1228 assert(N == 1 && "Invalid number of operands!");
1229 // The constant encodes as the immediate, except for 32, which encodes as
1230 // zero.
1231 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1232 unsigned Imm = CE->getValue();
1233 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1234 }
1235
Jim Grosbachf6c05252011-07-21 17:23:04 +00001236 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 addExpr(Inst, getImm());
1239 }
1240
1241 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1242 assert(N == 1 && "Invalid number of operands!");
1243 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1244 // the instruction as well.
1245 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1246 int Val = CE->getValue();
1247 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1248 }
1249
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001250 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1251 assert(N == 1 && "Invalid number of operands!");
1252 addExpr(Inst, getImm());
1253 }
1254
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001255 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
1257 addExpr(Inst, getImm());
1258 }
1259
Jim Grosbach89a63372011-10-28 22:36:30 +00001260 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
1262 // The operand is actually a t2_so_imm, but we have its bitwise
1263 // negation in the assembly source, so twiddle it here.
1264 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1265 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1266 }
1267
Jim Grosbache70ec842011-10-28 22:50:54 +00001268 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1269 assert(N == 1 && "Invalid number of operands!");
1270 // The operand is actually a so_imm, but we have its bitwise
1271 // negation in the assembly source, so twiddle it here.
1272 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1273 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1274 }
1275
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001276 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
1278 addExpr(Inst, getImm());
1279 }
1280
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001281 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1282 assert(N == 1 && "Invalid number of operands!");
1283 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1284 }
1285
Jim Grosbach7ce05792011-08-03 23:50:40 +00001286 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1287 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001288 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001289 }
1290
Jim Grosbach57dcb852011-10-11 17:29:55 +00001291 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1292 assert(N == 2 && "Invalid number of operands!");
1293 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1294 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1295 }
1296
Jim Grosbach7ce05792011-08-03 23:50:40 +00001297 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1298 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001299 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1300 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001301 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1302 // Special case for #-0
1303 if (Val == INT32_MIN) Val = 0;
1304 if (Val < 0) Val = -Val;
1305 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1306 } else {
1307 // For register offset, we encode the shift type and negation flag
1308 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001309 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1310 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001311 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001312 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1313 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001314 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001315 }
1316
Jim Grosbach039c2e12011-08-04 23:01:30 +00001317 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1318 assert(N == 2 && "Invalid number of operands!");
1319 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1320 assert(CE && "non-constant AM2OffsetImm operand!");
1321 int32_t Val = CE->getValue();
1322 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1323 // Special case for #-0
1324 if (Val == INT32_MIN) Val = 0;
1325 if (Val < 0) Val = -Val;
1326 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1327 Inst.addOperand(MCOperand::CreateReg(0));
1328 Inst.addOperand(MCOperand::CreateImm(Val));
1329 }
1330
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001331 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1332 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001333 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1334 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001335 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1336 // Special case for #-0
1337 if (Val == INT32_MIN) Val = 0;
1338 if (Val < 0) Val = -Val;
1339 Val = ARM_AM::getAM3Opc(AddSub, Val);
1340 } else {
1341 // For register offset, we encode the shift type and negation flag
1342 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001343 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001344 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001345 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1346 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001347 Inst.addOperand(MCOperand::CreateImm(Val));
1348 }
1349
1350 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1351 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001352 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001353 int32_t Val =
1354 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1355 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1356 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001357 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001358 }
1359
1360 // Constant offset.
1361 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1362 int32_t Val = CE->getValue();
1363 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1364 // Special case for #-0
1365 if (Val == INT32_MIN) Val = 0;
1366 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001367 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001368 Inst.addOperand(MCOperand::CreateReg(0));
1369 Inst.addOperand(MCOperand::CreateImm(Val));
1370 }
1371
Jim Grosbach7ce05792011-08-03 23:50:40 +00001372 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1373 assert(N == 2 && "Invalid number of operands!");
1374 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001375 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001376 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1377 // Special case for #-0
1378 if (Val == INT32_MIN) Val = 0;
1379 if (Val < 0) Val = -Val;
1380 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001381 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001382 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001383 }
1384
Jim Grosbacha77295d2011-09-08 22:07:06 +00001385 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001387 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1388 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001389 Inst.addOperand(MCOperand::CreateImm(Val));
1390 }
1391
Jim Grosbachb6aed502011-09-09 18:37:27 +00001392 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1393 assert(N == 2 && "Invalid number of operands!");
1394 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001395 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1396 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001397 Inst.addOperand(MCOperand::CreateImm(Val));
1398 }
1399
Jim Grosbach7ce05792011-08-03 23:50:40 +00001400 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1401 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001402 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1403 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001404 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001405 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001406
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001407 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1408 addMemImm8OffsetOperands(Inst, N);
1409 }
1410
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001411 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001412 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001413 }
1414
1415 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1416 assert(N == 2 && "Invalid number of operands!");
1417 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001418 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001419 addExpr(Inst, getImm());
1420 Inst.addOperand(MCOperand::CreateImm(0));
1421 return;
1422 }
1423
1424 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001425 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1426 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001427 Inst.addOperand(MCOperand::CreateImm(Val));
1428 }
1429
Jim Grosbach7ce05792011-08-03 23:50:40 +00001430 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001432 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001433 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001434 addExpr(Inst, getImm());
1435 Inst.addOperand(MCOperand::CreateImm(0));
1436 return;
1437 }
1438
1439 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001440 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1441 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001442 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001443 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001444
Jim Grosbach7f739be2011-09-19 22:21:13 +00001445 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001447 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1448 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001449 }
1450
1451 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001453 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1454 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001455 }
1456
Jim Grosbach7ce05792011-08-03 23:50:40 +00001457 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1458 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001459 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1460 Memory.ShiftImm, Memory.ShiftType);
1461 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1462 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001463 Inst.addOperand(MCOperand::CreateImm(Val));
1464 }
1465
Jim Grosbachab899c12011-09-07 23:10:15 +00001466 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1467 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001468 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1469 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1470 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001471 }
1472
Jim Grosbach7ce05792011-08-03 23:50:40 +00001473 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001475 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1476 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001477 }
1478
Jim Grosbach60f91a32011-08-19 17:55:24 +00001479 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1480 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001481 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1482 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001483 Inst.addOperand(MCOperand::CreateImm(Val));
1484 }
1485
Jim Grosbach38466302011-08-19 18:55:51 +00001486 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1487 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001488 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1489 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001490 Inst.addOperand(MCOperand::CreateImm(Val));
1491 }
1492
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001493 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1494 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001495 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1496 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001497 Inst.addOperand(MCOperand::CreateImm(Val));
1498 }
1499
Jim Grosbachecd85892011-08-19 18:13:48 +00001500 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1501 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001502 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1503 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001504 Inst.addOperand(MCOperand::CreateImm(Val));
1505 }
1506
Jim Grosbach7ce05792011-08-03 23:50:40 +00001507 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
1509 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1510 assert(CE && "non-constant post-idx-imm8 operand!");
1511 int Imm = CE->getValue();
1512 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001513 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001514 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1515 Inst.addOperand(MCOperand::CreateImm(Imm));
1516 }
1517
Jim Grosbach2bd01182011-10-11 21:55:36 +00001518 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1519 assert(N == 1 && "Invalid number of operands!");
1520 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1521 assert(CE && "non-constant post-idx-imm8s4 operand!");
1522 int Imm = CE->getValue();
1523 bool isAdd = Imm >= 0;
1524 if (Imm == INT32_MIN) Imm = 0;
1525 // Immediate is scaled by 4.
1526 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1527 Inst.addOperand(MCOperand::CreateImm(Imm));
1528 }
1529
Jim Grosbach7ce05792011-08-03 23:50:40 +00001530 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 2 && "Invalid number of operands!");
1532 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001533 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1534 }
1535
1536 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1537 assert(N == 2 && "Invalid number of operands!");
1538 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1539 // The sign, shift type, and shift amount are encoded in a single operand
1540 // using the AM2 encoding helpers.
1541 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1542 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1543 PostIdxReg.ShiftTy);
1544 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001545 }
1546
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001547 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 1 && "Invalid number of operands!");
1549 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1550 }
1551
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001552 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1555 }
1556
Jim Grosbach862019c2011-10-18 23:02:30 +00001557 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1558 assert(N == 1 && "Invalid number of operands!");
1559 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1560 }
1561
Jim Grosbach280dfad2011-10-21 18:54:25 +00001562 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1563 assert(N == 1 && "Invalid number of operands!");
1564 // Only the first register actually goes on the instruction. The rest
1565 // are implied by the opcode.
1566 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1567 }
1568
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001569 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1570 assert(N == 1 && "Invalid number of operands!");
1571 // Only the first register actually goes on the instruction. The rest
1572 // are implied by the opcode.
1573 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1574 }
1575
Jim Grosbachb6310312011-10-21 20:35:01 +00001576 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1577 assert(N == 1 && "Invalid number of operands!");
1578 // Only the first register actually goes on the instruction. The rest
1579 // are implied by the opcode.
1580 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1581 }
1582
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001583 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 1 && "Invalid number of operands!");
1585 // Only the first register actually goes on the instruction. The rest
1586 // are implied by the opcode.
1587 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1588 }
1589
Jim Grosbach460a9052011-10-07 23:56:00 +00001590 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1591 assert(N == 1 && "Invalid number of operands!");
1592 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1593 }
1594
1595 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1596 assert(N == 1 && "Invalid number of operands!");
1597 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1598 }
1599
1600 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1601 assert(N == 1 && "Invalid number of operands!");
1602 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1603 }
1604
Jim Grosbach0e387b22011-10-17 22:26:03 +00001605 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1606 assert(N == 1 && "Invalid number of operands!");
1607 // The immediate encodes the type of constant as well as the value.
1608 // Mask in that this is an i8 splat.
1609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1610 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1611 }
1612
Jim Grosbachea461102011-10-17 23:09:09 +00001613 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 // The immediate encodes the type of constant as well as the value.
1616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1617 unsigned Value = CE->getValue();
1618 if (Value >= 256)
1619 Value = (Value >> 8) | 0xa00;
1620 else
1621 Value |= 0x800;
1622 Inst.addOperand(MCOperand::CreateImm(Value));
1623 }
1624
Jim Grosbach6248a542011-10-18 00:22:00 +00001625 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1626 assert(N == 1 && "Invalid number of operands!");
1627 // The immediate encodes the type of constant as well as the value.
1628 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1629 unsigned Value = CE->getValue();
1630 if (Value >= 256 && Value <= 0xff00)
1631 Value = (Value >> 8) | 0x200;
1632 else if (Value > 0xffff && Value <= 0xff0000)
1633 Value = (Value >> 16) | 0x400;
1634 else if (Value > 0xffffff)
1635 Value = (Value >> 24) | 0x600;
1636 Inst.addOperand(MCOperand::CreateImm(Value));
1637 }
1638
1639 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1640 assert(N == 1 && "Invalid number of operands!");
1641 // The immediate encodes the type of constant as well as the value.
1642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1643 unsigned Value = CE->getValue();
1644 if (Value >= 256 && Value <= 0xffff)
1645 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1646 else if (Value > 0xffff && Value <= 0xffffff)
1647 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1648 else if (Value > 0xffffff)
1649 Value = (Value >> 24) | 0x600;
1650 Inst.addOperand(MCOperand::CreateImm(Value));
1651 }
1652
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001653 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1654 assert(N == 1 && "Invalid number of operands!");
1655 // The immediate encodes the type of constant as well as the value.
1656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1657 uint64_t Value = CE->getValue();
1658 unsigned Imm = 0;
1659 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1660 Imm |= (Value & 1) << i;
1661 }
1662 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1663 }
1664
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001665 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001666
Jim Grosbach89df9962011-08-26 21:43:41 +00001667 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001668 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001669 Op->ITMask.Mask = Mask;
1670 Op->StartLoc = S;
1671 Op->EndLoc = S;
1672 return Op;
1673 }
1674
Chris Lattner3a697562010-10-28 17:20:03 +00001675 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001676 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001677 Op->CC.Val = CC;
1678 Op->StartLoc = S;
1679 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001680 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001681 }
1682
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001683 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001684 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001685 Op->Cop.Val = CopVal;
1686 Op->StartLoc = S;
1687 Op->EndLoc = S;
1688 return Op;
1689 }
1690
1691 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001692 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001693 Op->Cop.Val = CopVal;
1694 Op->StartLoc = S;
1695 Op->EndLoc = S;
1696 return Op;
1697 }
1698
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001699 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1700 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1701 Op->Cop.Val = Val;
1702 Op->StartLoc = S;
1703 Op->EndLoc = E;
1704 return Op;
1705 }
1706
Jim Grosbachd67641b2010-12-06 18:21:12 +00001707 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001708 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001709 Op->Reg.RegNum = RegNum;
1710 Op->StartLoc = S;
1711 Op->EndLoc = S;
1712 return Op;
1713 }
1714
Chris Lattner3a697562010-10-28 17:20:03 +00001715 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001716 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001717 Op->Tok.Data = Str.data();
1718 Op->Tok.Length = Str.size();
1719 Op->StartLoc = S;
1720 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001721 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001722 }
1723
Bill Wendling50d0f582010-11-18 23:43:05 +00001724 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001725 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001726 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001727 Op->StartLoc = S;
1728 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001729 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001730 }
1731
Jim Grosbache8606dc2011-07-13 17:50:29 +00001732 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1733 unsigned SrcReg,
1734 unsigned ShiftReg,
1735 unsigned ShiftImm,
1736 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001737 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001738 Op->RegShiftedReg.ShiftTy = ShTy;
1739 Op->RegShiftedReg.SrcReg = SrcReg;
1740 Op->RegShiftedReg.ShiftReg = ShiftReg;
1741 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001742 Op->StartLoc = S;
1743 Op->EndLoc = E;
1744 return Op;
1745 }
1746
Owen Anderson92a20222011-07-21 18:54:16 +00001747 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1748 unsigned SrcReg,
1749 unsigned ShiftImm,
1750 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001751 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001752 Op->RegShiftedImm.ShiftTy = ShTy;
1753 Op->RegShiftedImm.SrcReg = SrcReg;
1754 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001755 Op->StartLoc = S;
1756 Op->EndLoc = E;
1757 return Op;
1758 }
1759
Jim Grosbach580f4a92011-07-25 22:20:28 +00001760 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001761 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001762 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001763 Op->ShifterImm.isASR = isASR;
1764 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001765 Op->StartLoc = S;
1766 Op->EndLoc = E;
1767 return Op;
1768 }
1769
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001770 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001771 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001772 Op->RotImm.Imm = Imm;
1773 Op->StartLoc = S;
1774 Op->EndLoc = E;
1775 return Op;
1776 }
1777
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001778 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1779 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001780 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001781 Op->Bitfield.LSB = LSB;
1782 Op->Bitfield.Width = Width;
1783 Op->StartLoc = S;
1784 Op->EndLoc = E;
1785 return Op;
1786 }
1787
Bill Wendling7729e062010-11-09 22:44:22 +00001788 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001789 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001790 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001791 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001792
Jim Grosbachd300b942011-09-13 22:56:44 +00001793 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001794 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001795 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001796 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001797 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001798
1799 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001800 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001801 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001802 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001803 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001804 Op->StartLoc = StartLoc;
1805 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001806 return Op;
1807 }
1808
Jim Grosbach862019c2011-10-18 23:02:30 +00001809 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1810 SMLoc S, SMLoc E) {
1811 ARMOperand *Op = new ARMOperand(k_VectorList);
1812 Op->VectorList.RegNum = RegNum;
1813 Op->VectorList.Count = Count;
1814 Op->StartLoc = S;
1815 Op->EndLoc = E;
1816 return Op;
1817 }
1818
Jim Grosbach460a9052011-10-07 23:56:00 +00001819 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1820 MCContext &Ctx) {
1821 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1822 Op->VectorIndex.Val = Idx;
1823 Op->StartLoc = S;
1824 Op->EndLoc = E;
1825 return Op;
1826 }
1827
Chris Lattner3a697562010-10-28 17:20:03 +00001828 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001829 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001830 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001831 Op->StartLoc = S;
1832 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001833 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001834 }
1835
Jim Grosbach9d390362011-10-03 23:38:36 +00001836 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001837 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001838 Op->FPImm.Val = Val;
1839 Op->StartLoc = S;
1840 Op->EndLoc = S;
1841 return Op;
1842 }
1843
Jim Grosbach7ce05792011-08-03 23:50:40 +00001844 static ARMOperand *CreateMem(unsigned BaseRegNum,
1845 const MCConstantExpr *OffsetImm,
1846 unsigned OffsetRegNum,
1847 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001848 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001849 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001850 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001851 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001852 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001853 Op->Memory.BaseRegNum = BaseRegNum;
1854 Op->Memory.OffsetImm = OffsetImm;
1855 Op->Memory.OffsetRegNum = OffsetRegNum;
1856 Op->Memory.ShiftType = ShiftType;
1857 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001858 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001859 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001860 Op->StartLoc = S;
1861 Op->EndLoc = E;
1862 return Op;
1863 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001864
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001865 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1866 ARM_AM::ShiftOpc ShiftTy,
1867 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001868 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001869 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001870 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001871 Op->PostIdxReg.isAdd = isAdd;
1872 Op->PostIdxReg.ShiftTy = ShiftTy;
1873 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001874 Op->StartLoc = S;
1875 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001876 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001877 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001878
1879 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001880 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001881 Op->MBOpt.Val = Opt;
1882 Op->StartLoc = S;
1883 Op->EndLoc = S;
1884 return Op;
1885 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001886
1887 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001888 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001889 Op->IFlags.Val = IFlags;
1890 Op->StartLoc = S;
1891 Op->EndLoc = S;
1892 return Op;
1893 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001894
1895 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001896 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001897 Op->MMask.Val = MMask;
1898 Op->StartLoc = S;
1899 Op->EndLoc = S;
1900 return Op;
1901 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001902};
1903
1904} // end anonymous namespace.
1905
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001906void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001907 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001908 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001909 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1910 << ") >";
1911 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001912 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001913 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001914 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001916 OS << "<ccout " << getReg() << ">";
1917 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001918 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001919 static const char *MaskStr[] = {
1920 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1921 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1922 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001923 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1924 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1925 break;
1926 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001927 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001928 OS << "<coprocessor number: " << getCoproc() << ">";
1929 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001930 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001931 OS << "<coprocessor register: " << getCoproc() << ">";
1932 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001933 case k_CoprocOption:
1934 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1935 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001936 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001937 OS << "<mask: " << getMSRMask() << ">";
1938 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001939 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001940 getImm()->print(OS);
1941 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001942 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001943 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1944 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001945 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001946 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001947 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001948 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001949 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001950 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001951 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1952 << PostIdxReg.RegNum;
1953 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1954 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1955 << PostIdxReg.ShiftImm;
1956 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001957 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001958 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001959 OS << "<ARM_PROC::";
1960 unsigned IFlags = getProcIFlags();
1961 for (int i=2; i >= 0; --i)
1962 if (IFlags & (1 << i))
1963 OS << ARM_PROC::IFlagsToString(1 << i);
1964 OS << ">";
1965 break;
1966 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001967 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001968 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001969 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001970 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001971 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1972 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001973 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001974 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001975 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001976 << RegShiftedReg.SrcReg
1977 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1978 << ", " << RegShiftedReg.ShiftReg << ", "
1979 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001980 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001981 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001982 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001983 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001984 << RegShiftedImm.SrcReg
1985 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1986 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001987 << ">";
1988 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001989 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001990 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1991 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001992 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001993 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1994 << ", width: " << Bitfield.Width << ">";
1995 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001996 case k_RegisterList:
1997 case k_DPRRegisterList:
1998 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001999 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002000
Bill Wendling5fa22a12010-11-09 23:28:44 +00002001 const SmallVectorImpl<unsigned> &RegList = getRegList();
2002 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002003 I = RegList.begin(), E = RegList.end(); I != E; ) {
2004 OS << *I;
2005 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002006 }
2007
2008 OS << ">";
2009 break;
2010 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002011 case k_VectorList:
2012 OS << "<vector_list " << VectorList.Count << " * "
2013 << VectorList.RegNum << ">";
2014 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002015 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002016 OS << "'" << getToken() << "'";
2017 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002018 case k_VectorIndex:
2019 OS << "<vectorindex " << getVectorIndex() << ">";
2020 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002021 }
2022}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002023
2024/// @name Auto-generated Match Functions
2025/// {
2026
2027static unsigned MatchRegisterName(StringRef Name);
2028
2029/// }
2030
Bob Wilson69df7232011-02-03 21:46:10 +00002031bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2032 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002033 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002034
2035 return (RegNo == (unsigned)-1);
2036}
2037
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002038/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002039/// and if it is a register name the token is eaten and the register number is
2040/// returned. Otherwise return -1.
2041///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002042int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002043 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002044 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002045
Chris Lattnere5658fa2010-10-30 04:09:10 +00002046 // FIXME: Validate register for the current architecture; we have to do
2047 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00002048 std::string upperCase = Tok.getString().str();
2049 std::string lowerCase = LowercaseString(upperCase);
2050 unsigned RegNum = MatchRegisterName(lowerCase);
2051 if (!RegNum) {
2052 RegNum = StringSwitch<unsigned>(lowerCase)
2053 .Case("r13", ARM::SP)
2054 .Case("r14", ARM::LR)
2055 .Case("r15", ARM::PC)
2056 .Case("ip", ARM::R12)
2057 .Default(0);
2058 }
2059 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002060
Chris Lattnere5658fa2010-10-30 04:09:10 +00002061 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002062
Chris Lattnere5658fa2010-10-30 04:09:10 +00002063 return RegNum;
2064}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002065
Jim Grosbach19906722011-07-13 18:49:30 +00002066// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2067// If a recoverable error occurs, return 1. If an irrecoverable error
2068// occurs, return -1. An irrecoverable error is one where tokens have been
2069// consumed in the process of trying to parse the shifter (i.e., when it is
2070// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002071int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002072 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2073 SMLoc S = Parser.getTok().getLoc();
2074 const AsmToken &Tok = Parser.getTok();
2075 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2076
2077 std::string upperCase = Tok.getString().str();
2078 std::string lowerCase = LowercaseString(upperCase);
2079 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2080 .Case("lsl", ARM_AM::lsl)
2081 .Case("lsr", ARM_AM::lsr)
2082 .Case("asr", ARM_AM::asr)
2083 .Case("ror", ARM_AM::ror)
2084 .Case("rrx", ARM_AM::rrx)
2085 .Default(ARM_AM::no_shift);
2086
2087 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002088 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002089
Jim Grosbache8606dc2011-07-13 17:50:29 +00002090 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002091
Jim Grosbache8606dc2011-07-13 17:50:29 +00002092 // The source register for the shift has already been added to the
2093 // operand list, so we need to pop it off and combine it into the shifted
2094 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002095 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002096 if (!PrevOp->isReg())
2097 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2098 int SrcReg = PrevOp->getReg();
2099 int64_t Imm = 0;
2100 int ShiftReg = 0;
2101 if (ShiftTy == ARM_AM::rrx) {
2102 // RRX Doesn't have an explicit shift amount. The encoder expects
2103 // the shift register to be the same as the source register. Seems odd,
2104 // but OK.
2105 ShiftReg = SrcReg;
2106 } else {
2107 // Figure out if this is shifted by a constant or a register (for non-RRX).
2108 if (Parser.getTok().is(AsmToken::Hash)) {
2109 Parser.Lex(); // Eat hash.
2110 SMLoc ImmLoc = Parser.getTok().getLoc();
2111 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002112 if (getParser().ParseExpression(ShiftExpr)) {
2113 Error(ImmLoc, "invalid immediate shift value");
2114 return -1;
2115 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002116 // The expression must be evaluatable as an immediate.
2117 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002118 if (!CE) {
2119 Error(ImmLoc, "invalid immediate shift value");
2120 return -1;
2121 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002122 // Range check the immediate.
2123 // lsl, ror: 0 <= imm <= 31
2124 // lsr, asr: 0 <= imm <= 32
2125 Imm = CE->getValue();
2126 if (Imm < 0 ||
2127 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2128 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002129 Error(ImmLoc, "immediate shift value out of range");
2130 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002131 }
2132 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002133 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002134 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002135 if (ShiftReg == -1) {
2136 Error (L, "expected immediate or register in shift operand");
2137 return -1;
2138 }
2139 } else {
2140 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002141 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002142 return -1;
2143 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002144 }
2145
Owen Anderson92a20222011-07-21 18:54:16 +00002146 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2147 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002148 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002149 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002150 else
2151 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2152 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002153
Jim Grosbach19906722011-07-13 18:49:30 +00002154 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002155}
2156
2157
Bill Wendling50d0f582010-11-18 23:43:05 +00002158/// Try to parse a register name. The token must be an Identifier when called.
2159/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2160/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002161///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002162/// TODO this is likely to change to allow different register types and or to
2163/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002164bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002165tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002166 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002167 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002168 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002169 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002170
Bill Wendling50d0f582010-11-18 23:43:05 +00002171 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002172
Chris Lattnere5658fa2010-10-30 04:09:10 +00002173 const AsmToken &ExclaimTok = Parser.getTok();
2174 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002175 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2176 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002177 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002178 return false;
2179 }
2180
2181 // Also check for an index operand. This is only legal for vector registers,
2182 // but that'll get caught OK in operand matching, so we don't need to
2183 // explicitly filter everything else out here.
2184 if (Parser.getTok().is(AsmToken::LBrac)) {
2185 SMLoc SIdx = Parser.getTok().getLoc();
2186 Parser.Lex(); // Eat left bracket token.
2187
2188 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002189 if (getParser().ParseExpression(ImmVal))
2190 return MatchOperand_ParseFail;
2191 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2192 if (!MCE) {
2193 TokError("immediate value expected for vector index");
2194 return MatchOperand_ParseFail;
2195 }
2196
2197 SMLoc E = Parser.getTok().getLoc();
2198 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2199 Error(E, "']' expected");
2200 return MatchOperand_ParseFail;
2201 }
2202
2203 Parser.Lex(); // Eat right bracket token.
2204
2205 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2206 SIdx, E,
2207 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002208 }
2209
Bill Wendling50d0f582010-11-18 23:43:05 +00002210 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002211}
2212
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002213/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2214/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2215/// "c5", ...
2216static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002217 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2218 // but efficient.
2219 switch (Name.size()) {
2220 default: break;
2221 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002222 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002223 return -1;
2224 switch (Name[1]) {
2225 default: return -1;
2226 case '0': return 0;
2227 case '1': return 1;
2228 case '2': return 2;
2229 case '3': return 3;
2230 case '4': return 4;
2231 case '5': return 5;
2232 case '6': return 6;
2233 case '7': return 7;
2234 case '8': return 8;
2235 case '9': return 9;
2236 }
2237 break;
2238 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002239 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002240 return -1;
2241 switch (Name[2]) {
2242 default: return -1;
2243 case '0': return 10;
2244 case '1': return 11;
2245 case '2': return 12;
2246 case '3': return 13;
2247 case '4': return 14;
2248 case '5': return 15;
2249 }
2250 break;
2251 }
2252
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002253 return -1;
2254}
2255
Jim Grosbach89df9962011-08-26 21:43:41 +00002256/// parseITCondCode - Try to parse a condition code for an IT instruction.
2257ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2258parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2259 SMLoc S = Parser.getTok().getLoc();
2260 const AsmToken &Tok = Parser.getTok();
2261 if (!Tok.is(AsmToken::Identifier))
2262 return MatchOperand_NoMatch;
2263 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2264 .Case("eq", ARMCC::EQ)
2265 .Case("ne", ARMCC::NE)
2266 .Case("hs", ARMCC::HS)
2267 .Case("cs", ARMCC::HS)
2268 .Case("lo", ARMCC::LO)
2269 .Case("cc", ARMCC::LO)
2270 .Case("mi", ARMCC::MI)
2271 .Case("pl", ARMCC::PL)
2272 .Case("vs", ARMCC::VS)
2273 .Case("vc", ARMCC::VC)
2274 .Case("hi", ARMCC::HI)
2275 .Case("ls", ARMCC::LS)
2276 .Case("ge", ARMCC::GE)
2277 .Case("lt", ARMCC::LT)
2278 .Case("gt", ARMCC::GT)
2279 .Case("le", ARMCC::LE)
2280 .Case("al", ARMCC::AL)
2281 .Default(~0U);
2282 if (CC == ~0U)
2283 return MatchOperand_NoMatch;
2284 Parser.Lex(); // Eat the token.
2285
2286 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2287
2288 return MatchOperand_Success;
2289}
2290
Jim Grosbach43904292011-07-25 20:14:50 +00002291/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002292/// token must be an Identifier when called, and if it is a coprocessor
2293/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002294ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002295parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002296 SMLoc S = Parser.getTok().getLoc();
2297 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002298 if (Tok.isNot(AsmToken::Identifier))
2299 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002300
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002301 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002302 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002303 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002304
2305 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002306 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002307 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002308}
2309
Jim Grosbach43904292011-07-25 20:14:50 +00002310/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002311/// token must be an Identifier when called, and if it is a coprocessor
2312/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002313ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002314parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002315 SMLoc S = Parser.getTok().getLoc();
2316 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002317 if (Tok.isNot(AsmToken::Identifier))
2318 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002319
2320 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2321 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002322 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002323
2324 Parser.Lex(); // Eat identifier token.
2325 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002326 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002327}
2328
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002329/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2330/// coproc_option : '{' imm0_255 '}'
2331ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2332parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2333 SMLoc S = Parser.getTok().getLoc();
2334
2335 // If this isn't a '{', this isn't a coprocessor immediate operand.
2336 if (Parser.getTok().isNot(AsmToken::LCurly))
2337 return MatchOperand_NoMatch;
2338 Parser.Lex(); // Eat the '{'
2339
2340 const MCExpr *Expr;
2341 SMLoc Loc = Parser.getTok().getLoc();
2342 if (getParser().ParseExpression(Expr)) {
2343 Error(Loc, "illegal expression");
2344 return MatchOperand_ParseFail;
2345 }
2346 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2347 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2348 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2349 return MatchOperand_ParseFail;
2350 }
2351 int Val = CE->getValue();
2352
2353 // Check for and consume the closing '}'
2354 if (Parser.getTok().isNot(AsmToken::RCurly))
2355 return MatchOperand_ParseFail;
2356 SMLoc E = Parser.getTok().getLoc();
2357 Parser.Lex(); // Eat the '}'
2358
2359 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2360 return MatchOperand_Success;
2361}
2362
Jim Grosbachd0588e22011-09-14 18:08:35 +00002363// For register list parsing, we need to map from raw GPR register numbering
2364// to the enumeration values. The enumeration values aren't sorted by
2365// register number due to our using "sp", "lr" and "pc" as canonical names.
2366static unsigned getNextRegister(unsigned Reg) {
2367 // If this is a GPR, we need to do it manually, otherwise we can rely
2368 // on the sort ordering of the enumeration since the other reg-classes
2369 // are sane.
2370 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2371 return Reg + 1;
2372 switch(Reg) {
2373 default: assert(0 && "Invalid GPR number!");
2374 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2375 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2376 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2377 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2378 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2379 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2380 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2381 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2382 }
2383}
2384
2385/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002386bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002387parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002388 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002389 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002390 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002391 Parser.Lex(); // Eat '{' token.
2392 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002393
Jim Grosbachd0588e22011-09-14 18:08:35 +00002394 // Check the first register in the list to see what register class
2395 // this is a list of.
2396 int Reg = tryParseRegister();
2397 if (Reg == -1)
2398 return Error(RegLoc, "register expected");
2399
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002400 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002401 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2402 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2403 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2404 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2405 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2406 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2407 else
2408 return Error(RegLoc, "invalid register in register list");
2409
2410 // The reglist instructions have at most 16 registers, so reserve
2411 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002412 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002413 // Store the first register.
2414 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002415
Jim Grosbachd0588e22011-09-14 18:08:35 +00002416 // This starts immediately after the first register token in the list,
2417 // so we can see either a comma or a minus (range separator) as a legal
2418 // next token.
2419 while (Parser.getTok().is(AsmToken::Comma) ||
2420 Parser.getTok().is(AsmToken::Minus)) {
2421 if (Parser.getTok().is(AsmToken::Minus)) {
2422 Parser.Lex(); // Eat the comma.
2423 SMLoc EndLoc = Parser.getTok().getLoc();
2424 int EndReg = tryParseRegister();
2425 if (EndReg == -1)
2426 return Error(EndLoc, "register expected");
2427 // If the register is the same as the start reg, there's nothing
2428 // more to do.
2429 if (Reg == EndReg)
2430 continue;
2431 // The register must be in the same register class as the first.
2432 if (!RC->contains(EndReg))
2433 return Error(EndLoc, "invalid register in register list");
2434 // Ranges must go from low to high.
2435 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2436 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002437
Jim Grosbachd0588e22011-09-14 18:08:35 +00002438 // Add all the registers in the range to the register list.
2439 while (Reg != EndReg) {
2440 Reg = getNextRegister(Reg);
2441 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2442 }
2443 continue;
2444 }
2445 Parser.Lex(); // Eat the comma.
2446 RegLoc = Parser.getTok().getLoc();
2447 int OldReg = Reg;
2448 Reg = tryParseRegister();
2449 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002450 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002451 // The register must be in the same register class as the first.
2452 if (!RC->contains(Reg))
2453 return Error(RegLoc, "invalid register in register list");
2454 // List must be monotonically increasing.
2455 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2456 return Error(RegLoc, "register list not in ascending order");
2457 // VFP register lists must also be contiguous.
2458 // It's OK to use the enumeration values directly here rather, as the
2459 // VFP register classes have the enum sorted properly.
2460 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2461 Reg != OldReg + 1)
2462 return Error(RegLoc, "non-contiguous register range");
2463 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002464 }
2465
Jim Grosbachd0588e22011-09-14 18:08:35 +00002466 SMLoc E = Parser.getTok().getLoc();
2467 if (Parser.getTok().isNot(AsmToken::RCurly))
2468 return Error(E, "'}' expected");
2469 Parser.Lex(); // Eat '}' token.
2470
Bill Wendling50d0f582010-11-18 23:43:05 +00002471 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2472 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002473}
2474
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002475// Return the low-subreg of a given Q register.
2476static unsigned getDRegFromQReg(unsigned QReg) {
2477 switch (QReg) {
2478 default: llvm_unreachable("expected a Q register!");
2479 case ARM::Q0: return ARM::D0;
2480 case ARM::Q1: return ARM::D2;
2481 case ARM::Q2: return ARM::D4;
2482 case ARM::Q3: return ARM::D6;
2483 case ARM::Q4: return ARM::D8;
2484 case ARM::Q5: return ARM::D10;
2485 case ARM::Q6: return ARM::D12;
2486 case ARM::Q7: return ARM::D14;
2487 case ARM::Q8: return ARM::D16;
2488 case ARM::Q9: return ARM::D19;
2489 case ARM::Q10: return ARM::D20;
2490 case ARM::Q11: return ARM::D22;
2491 case ARM::Q12: return ARM::D24;
2492 case ARM::Q13: return ARM::D26;
2493 case ARM::Q14: return ARM::D28;
2494 case ARM::Q15: return ARM::D30;
2495 }
2496}
2497
Jim Grosbach862019c2011-10-18 23:02:30 +00002498// parse a vector register list
2499ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2500parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2501 if(Parser.getTok().isNot(AsmToken::LCurly))
2502 return MatchOperand_NoMatch;
2503
2504 SMLoc S = Parser.getTok().getLoc();
2505 Parser.Lex(); // Eat '{' token.
2506 SMLoc RegLoc = Parser.getTok().getLoc();
2507
2508 int Reg = tryParseRegister();
2509 if (Reg == -1) {
2510 Error(RegLoc, "register expected");
2511 return MatchOperand_ParseFail;
2512 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002513 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002514 unsigned FirstReg = Reg;
2515 // The list is of D registers, but we also allow Q regs and just interpret
2516 // them as the two D sub-registers.
2517 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2518 FirstReg = Reg = getDRegFromQReg(Reg);
2519 ++Reg;
2520 ++Count;
2521 }
2522
Jim Grosbach862019c2011-10-18 23:02:30 +00002523 while (Parser.getTok().is(AsmToken::Comma)) {
2524 Parser.Lex(); // Eat the comma.
2525 RegLoc = Parser.getTok().getLoc();
2526 int OldReg = Reg;
2527 Reg = tryParseRegister();
2528 if (Reg == -1) {
2529 Error(RegLoc, "register expected");
2530 return MatchOperand_ParseFail;
2531 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002532 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002533 // It's OK to use the enumeration values directly here rather, as the
2534 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002535 //
2536 // The list is of D registers, but we also allow Q regs and just interpret
2537 // them as the two D sub-registers.
2538 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2539 Reg = getDRegFromQReg(Reg);
2540 if (Reg != OldReg + 1) {
2541 Error(RegLoc, "non-contiguous register range");
2542 return MatchOperand_ParseFail;
2543 }
2544 ++Reg;
2545 Count += 2;
2546 continue;
2547 }
2548 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002549 if (Reg != OldReg + 1) {
2550 Error(RegLoc, "non-contiguous register range");
2551 return MatchOperand_ParseFail;
2552 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002553 ++Count;
2554 }
2555
2556 SMLoc E = Parser.getTok().getLoc();
2557 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2558 Error(E, "'}' expected");
2559 return MatchOperand_ParseFail;
2560 }
2561 Parser.Lex(); // Eat '}' token.
2562
2563 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2564 return MatchOperand_Success;
2565}
2566
Jim Grosbach43904292011-07-25 20:14:50 +00002567/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002568ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002569parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002570 SMLoc S = Parser.getTok().getLoc();
2571 const AsmToken &Tok = Parser.getTok();
2572 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2573 StringRef OptStr = Tok.getString();
2574
2575 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2576 .Case("sy", ARM_MB::SY)
2577 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002578 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002579 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002580 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002581 .Case("ishst", ARM_MB::ISHST)
2582 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002583 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002584 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002585 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002586 .Case("osh", ARM_MB::OSH)
2587 .Case("oshst", ARM_MB::OSHST)
2588 .Default(~0U);
2589
2590 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002591 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002592
2593 Parser.Lex(); // Eat identifier token.
2594 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002595 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002596}
2597
Jim Grosbach43904292011-07-25 20:14:50 +00002598/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002599ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002600parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002601 SMLoc S = Parser.getTok().getLoc();
2602 const AsmToken &Tok = Parser.getTok();
2603 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2604 StringRef IFlagsStr = Tok.getString();
2605
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002606 // An iflags string of "none" is interpreted to mean that none of the AIF
2607 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002608 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002609 if (IFlagsStr != "none") {
2610 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2611 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2612 .Case("a", ARM_PROC::A)
2613 .Case("i", ARM_PROC::I)
2614 .Case("f", ARM_PROC::F)
2615 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002616
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002617 // If some specific iflag is already set, it means that some letter is
2618 // present more than once, this is not acceptable.
2619 if (Flag == ~0U || (IFlags & Flag))
2620 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002621
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002622 IFlags |= Flag;
2623 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002624 }
2625
2626 Parser.Lex(); // Eat identifier token.
2627 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2628 return MatchOperand_Success;
2629}
2630
Jim Grosbach43904292011-07-25 20:14:50 +00002631/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002632ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002633parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002634 SMLoc S = Parser.getTok().getLoc();
2635 const AsmToken &Tok = Parser.getTok();
2636 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2637 StringRef Mask = Tok.getString();
2638
James Molloyacad68d2011-09-28 14:21:38 +00002639 if (isMClass()) {
2640 // See ARMv6-M 10.1.1
2641 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2642 .Case("apsr", 0)
2643 .Case("iapsr", 1)
2644 .Case("eapsr", 2)
2645 .Case("xpsr", 3)
2646 .Case("ipsr", 5)
2647 .Case("epsr", 6)
2648 .Case("iepsr", 7)
2649 .Case("msp", 8)
2650 .Case("psp", 9)
2651 .Case("primask", 16)
2652 .Case("basepri", 17)
2653 .Case("basepri_max", 18)
2654 .Case("faultmask", 19)
2655 .Case("control", 20)
2656 .Default(~0U);
2657
2658 if (FlagsVal == ~0U)
2659 return MatchOperand_NoMatch;
2660
2661 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2662 // basepri, basepri_max and faultmask only valid for V7m.
2663 return MatchOperand_NoMatch;
2664
2665 Parser.Lex(); // Eat identifier token.
2666 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2667 return MatchOperand_Success;
2668 }
2669
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002670 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2671 size_t Start = 0, Next = Mask.find('_');
2672 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002673 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002674 if (Next != StringRef::npos)
2675 Flags = Mask.slice(Next+1, Mask.size());
2676
2677 // FlagsVal contains the complete mask:
2678 // 3-0: Mask
2679 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2680 unsigned FlagsVal = 0;
2681
2682 if (SpecReg == "apsr") {
2683 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002684 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002685 .Case("g", 0x4) // same as CPSR_s
2686 .Case("nzcvqg", 0xc) // same as CPSR_fs
2687 .Default(~0U);
2688
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002689 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002690 if (!Flags.empty())
2691 return MatchOperand_NoMatch;
2692 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002693 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002694 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002695 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002696 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2697 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002698 for (int i = 0, e = Flags.size(); i != e; ++i) {
2699 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2700 .Case("c", 1)
2701 .Case("x", 2)
2702 .Case("s", 4)
2703 .Case("f", 8)
2704 .Default(~0U);
2705
2706 // If some specific flag is already set, it means that some letter is
2707 // present more than once, this is not acceptable.
2708 if (FlagsVal == ~0U || (FlagsVal & Flag))
2709 return MatchOperand_NoMatch;
2710 FlagsVal |= Flag;
2711 }
2712 } else // No match for special register.
2713 return MatchOperand_NoMatch;
2714
Owen Anderson7784f1d2011-10-21 18:43:28 +00002715 // Special register without flags is NOT equivalent to "fc" flags.
2716 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2717 // two lines would enable gas compatibility at the expense of breaking
2718 // round-tripping.
2719 //
2720 // if (!FlagsVal)
2721 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002722
2723 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2724 if (SpecReg == "spsr")
2725 FlagsVal |= 16;
2726
2727 Parser.Lex(); // Eat identifier token.
2728 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2729 return MatchOperand_Success;
2730}
2731
Jim Grosbachf6c05252011-07-21 17:23:04 +00002732ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2733parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2734 int Low, int High) {
2735 const AsmToken &Tok = Parser.getTok();
2736 if (Tok.isNot(AsmToken::Identifier)) {
2737 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2738 return MatchOperand_ParseFail;
2739 }
2740 StringRef ShiftName = Tok.getString();
2741 std::string LowerOp = LowercaseString(Op);
2742 std::string UpperOp = UppercaseString(Op);
2743 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2744 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2745 return MatchOperand_ParseFail;
2746 }
2747 Parser.Lex(); // Eat shift type token.
2748
2749 // There must be a '#' and a shift amount.
2750 if (Parser.getTok().isNot(AsmToken::Hash)) {
2751 Error(Parser.getTok().getLoc(), "'#' expected");
2752 return MatchOperand_ParseFail;
2753 }
2754 Parser.Lex(); // Eat hash token.
2755
2756 const MCExpr *ShiftAmount;
2757 SMLoc Loc = Parser.getTok().getLoc();
2758 if (getParser().ParseExpression(ShiftAmount)) {
2759 Error(Loc, "illegal expression");
2760 return MatchOperand_ParseFail;
2761 }
2762 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2763 if (!CE) {
2764 Error(Loc, "constant expression expected");
2765 return MatchOperand_ParseFail;
2766 }
2767 int Val = CE->getValue();
2768 if (Val < Low || Val > High) {
2769 Error(Loc, "immediate value out of range");
2770 return MatchOperand_ParseFail;
2771 }
2772
2773 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2774
2775 return MatchOperand_Success;
2776}
2777
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002778ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2779parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2780 const AsmToken &Tok = Parser.getTok();
2781 SMLoc S = Tok.getLoc();
2782 if (Tok.isNot(AsmToken::Identifier)) {
2783 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2784 return MatchOperand_ParseFail;
2785 }
2786 int Val = StringSwitch<int>(Tok.getString())
2787 .Case("be", 1)
2788 .Case("le", 0)
2789 .Default(-1);
2790 Parser.Lex(); // Eat the token.
2791
2792 if (Val == -1) {
2793 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2794 return MatchOperand_ParseFail;
2795 }
2796 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2797 getContext()),
2798 S, Parser.getTok().getLoc()));
2799 return MatchOperand_Success;
2800}
2801
Jim Grosbach580f4a92011-07-25 22:20:28 +00002802/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2803/// instructions. Legal values are:
2804/// lsl #n 'n' in [0,31]
2805/// asr #n 'n' in [1,32]
2806/// n == 32 encoded as n == 0.
2807ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2808parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2809 const AsmToken &Tok = Parser.getTok();
2810 SMLoc S = Tok.getLoc();
2811 if (Tok.isNot(AsmToken::Identifier)) {
2812 Error(S, "shift operator 'asr' or 'lsl' expected");
2813 return MatchOperand_ParseFail;
2814 }
2815 StringRef ShiftName = Tok.getString();
2816 bool isASR;
2817 if (ShiftName == "lsl" || ShiftName == "LSL")
2818 isASR = false;
2819 else if (ShiftName == "asr" || ShiftName == "ASR")
2820 isASR = true;
2821 else {
2822 Error(S, "shift operator 'asr' or 'lsl' expected");
2823 return MatchOperand_ParseFail;
2824 }
2825 Parser.Lex(); // Eat the operator.
2826
2827 // A '#' and a shift amount.
2828 if (Parser.getTok().isNot(AsmToken::Hash)) {
2829 Error(Parser.getTok().getLoc(), "'#' expected");
2830 return MatchOperand_ParseFail;
2831 }
2832 Parser.Lex(); // Eat hash token.
2833
2834 const MCExpr *ShiftAmount;
2835 SMLoc E = Parser.getTok().getLoc();
2836 if (getParser().ParseExpression(ShiftAmount)) {
2837 Error(E, "malformed shift expression");
2838 return MatchOperand_ParseFail;
2839 }
2840 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2841 if (!CE) {
2842 Error(E, "shift amount must be an immediate");
2843 return MatchOperand_ParseFail;
2844 }
2845
2846 int64_t Val = CE->getValue();
2847 if (isASR) {
2848 // Shift amount must be in [1,32]
2849 if (Val < 1 || Val > 32) {
2850 Error(E, "'asr' shift amount must be in range [1,32]");
2851 return MatchOperand_ParseFail;
2852 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002853 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2854 if (isThumb() && Val == 32) {
2855 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2856 return MatchOperand_ParseFail;
2857 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002858 if (Val == 32) Val = 0;
2859 } else {
2860 // Shift amount must be in [1,32]
2861 if (Val < 0 || Val > 31) {
2862 Error(E, "'lsr' shift amount must be in range [0,31]");
2863 return MatchOperand_ParseFail;
2864 }
2865 }
2866
2867 E = Parser.getTok().getLoc();
2868 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2869
2870 return MatchOperand_Success;
2871}
2872
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002873/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2874/// of instructions. Legal values are:
2875/// ror #n 'n' in {0, 8, 16, 24}
2876ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2877parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2878 const AsmToken &Tok = Parser.getTok();
2879 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002880 if (Tok.isNot(AsmToken::Identifier))
2881 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002882 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002883 if (ShiftName != "ror" && ShiftName != "ROR")
2884 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002885 Parser.Lex(); // Eat the operator.
2886
2887 // A '#' and a rotate amount.
2888 if (Parser.getTok().isNot(AsmToken::Hash)) {
2889 Error(Parser.getTok().getLoc(), "'#' expected");
2890 return MatchOperand_ParseFail;
2891 }
2892 Parser.Lex(); // Eat hash token.
2893
2894 const MCExpr *ShiftAmount;
2895 SMLoc E = Parser.getTok().getLoc();
2896 if (getParser().ParseExpression(ShiftAmount)) {
2897 Error(E, "malformed rotate expression");
2898 return MatchOperand_ParseFail;
2899 }
2900 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2901 if (!CE) {
2902 Error(E, "rotate amount must be an immediate");
2903 return MatchOperand_ParseFail;
2904 }
2905
2906 int64_t Val = CE->getValue();
2907 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2908 // normally, zero is represented in asm by omitting the rotate operand
2909 // entirely.
2910 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2911 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2912 return MatchOperand_ParseFail;
2913 }
2914
2915 E = Parser.getTok().getLoc();
2916 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2917
2918 return MatchOperand_Success;
2919}
2920
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002921ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2922parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2923 SMLoc S = Parser.getTok().getLoc();
2924 // The bitfield descriptor is really two operands, the LSB and the width.
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 *LSBExpr;
2932 SMLoc E = Parser.getTok().getLoc();
2933 if (getParser().ParseExpression(LSBExpr)) {
2934 Error(E, "malformed immediate expression");
2935 return MatchOperand_ParseFail;
2936 }
2937 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2938 if (!CE) {
2939 Error(E, "'lsb' operand must be an immediate");
2940 return MatchOperand_ParseFail;
2941 }
2942
2943 int64_t LSB = CE->getValue();
2944 // The LSB must be in the range [0,31]
2945 if (LSB < 0 || LSB > 31) {
2946 Error(E, "'lsb' operand must be in the range [0,31]");
2947 return MatchOperand_ParseFail;
2948 }
2949 E = Parser.getTok().getLoc();
2950
2951 // Expect another immediate operand.
2952 if (Parser.getTok().isNot(AsmToken::Comma)) {
2953 Error(Parser.getTok().getLoc(), "too few operands");
2954 return MatchOperand_ParseFail;
2955 }
2956 Parser.Lex(); // Eat hash token.
2957 if (Parser.getTok().isNot(AsmToken::Hash)) {
2958 Error(Parser.getTok().getLoc(), "'#' expected");
2959 return MatchOperand_ParseFail;
2960 }
2961 Parser.Lex(); // Eat hash token.
2962
2963 const MCExpr *WidthExpr;
2964 if (getParser().ParseExpression(WidthExpr)) {
2965 Error(E, "malformed immediate expression");
2966 return MatchOperand_ParseFail;
2967 }
2968 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2969 if (!CE) {
2970 Error(E, "'width' operand must be an immediate");
2971 return MatchOperand_ParseFail;
2972 }
2973
2974 int64_t Width = CE->getValue();
2975 // The LSB must be in the range [1,32-lsb]
2976 if (Width < 1 || Width > 32 - LSB) {
2977 Error(E, "'width' operand must be in the range [1,32-lsb]");
2978 return MatchOperand_ParseFail;
2979 }
2980 E = Parser.getTok().getLoc();
2981
2982 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2983
2984 return MatchOperand_Success;
2985}
2986
Jim Grosbach7ce05792011-08-03 23:50:40 +00002987ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2988parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2989 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002990 // postidx_reg := '+' register {, shift}
2991 // | '-' register {, shift}
2992 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002993
2994 // This method must return MatchOperand_NoMatch without consuming any tokens
2995 // in the case where there is no match, as other alternatives take other
2996 // parse methods.
2997 AsmToken Tok = Parser.getTok();
2998 SMLoc S = Tok.getLoc();
2999 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003000 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003001 int Reg = -1;
3002 if (Tok.is(AsmToken::Plus)) {
3003 Parser.Lex(); // Eat the '+' token.
3004 haveEaten = true;
3005 } else if (Tok.is(AsmToken::Minus)) {
3006 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003007 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003008 haveEaten = true;
3009 }
3010 if (Parser.getTok().is(AsmToken::Identifier))
3011 Reg = tryParseRegister();
3012 if (Reg == -1) {
3013 if (!haveEaten)
3014 return MatchOperand_NoMatch;
3015 Error(Parser.getTok().getLoc(), "register expected");
3016 return MatchOperand_ParseFail;
3017 }
3018 SMLoc E = Parser.getTok().getLoc();
3019
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003020 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3021 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003022 if (Parser.getTok().is(AsmToken::Comma)) {
3023 Parser.Lex(); // Eat the ','.
3024 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3025 return MatchOperand_ParseFail;
3026 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003027
3028 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3029 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003030
3031 return MatchOperand_Success;
3032}
3033
Jim Grosbach251bf252011-08-10 21:56:18 +00003034ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3035parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3036 // Check for a post-index addressing register operand. Specifically:
3037 // am3offset := '+' register
3038 // | '-' register
3039 // | register
3040 // | # imm
3041 // | # + imm
3042 // | # - imm
3043
3044 // This method must return MatchOperand_NoMatch without consuming any tokens
3045 // in the case where there is no match, as other alternatives take other
3046 // parse methods.
3047 AsmToken Tok = Parser.getTok();
3048 SMLoc S = Tok.getLoc();
3049
3050 // Do immediates first, as we always parse those if we have a '#'.
3051 if (Parser.getTok().is(AsmToken::Hash)) {
3052 Parser.Lex(); // Eat the '#'.
3053 // Explicitly look for a '-', as we need to encode negative zero
3054 // differently.
3055 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3056 const MCExpr *Offset;
3057 if (getParser().ParseExpression(Offset))
3058 return MatchOperand_ParseFail;
3059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3060 if (!CE) {
3061 Error(S, "constant expression expected");
3062 return MatchOperand_ParseFail;
3063 }
3064 SMLoc E = Tok.getLoc();
3065 // Negative zero is encoded as the flag value INT32_MIN.
3066 int32_t Val = CE->getValue();
3067 if (isNegative && Val == 0)
3068 Val = INT32_MIN;
3069
3070 Operands.push_back(
3071 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3072
3073 return MatchOperand_Success;
3074 }
3075
3076
3077 bool haveEaten = false;
3078 bool isAdd = true;
3079 int Reg = -1;
3080 if (Tok.is(AsmToken::Plus)) {
3081 Parser.Lex(); // Eat the '+' token.
3082 haveEaten = true;
3083 } else if (Tok.is(AsmToken::Minus)) {
3084 Parser.Lex(); // Eat the '-' token.
3085 isAdd = false;
3086 haveEaten = true;
3087 }
3088 if (Parser.getTok().is(AsmToken::Identifier))
3089 Reg = tryParseRegister();
3090 if (Reg == -1) {
3091 if (!haveEaten)
3092 return MatchOperand_NoMatch;
3093 Error(Parser.getTok().getLoc(), "register expected");
3094 return MatchOperand_ParseFail;
3095 }
3096 SMLoc E = Parser.getTok().getLoc();
3097
3098 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3099 0, S, E));
3100
3101 return MatchOperand_Success;
3102}
3103
Jim Grosbacha77295d2011-09-08 22:07:06 +00003104/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3105/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3106/// when they refer multiple MIOperands inside a single one.
3107bool ARMAsmParser::
3108cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3109 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3110 // Rt, Rt2
3111 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3112 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3113 // Create a writeback register dummy placeholder.
3114 Inst.addOperand(MCOperand::CreateReg(0));
3115 // addr
3116 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3117 // pred
3118 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3119 return true;
3120}
3121
3122/// cvtT2StrdPre - Convert parsed operands to MCInst.
3123/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3124/// when they refer multiple MIOperands inside a single one.
3125bool ARMAsmParser::
3126cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3127 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3128 // Create a writeback register dummy placeholder.
3129 Inst.addOperand(MCOperand::CreateReg(0));
3130 // Rt, Rt2
3131 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3132 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3133 // addr
3134 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3135 // pred
3136 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3137 return true;
3138}
3139
Jim Grosbacheeec0252011-09-08 00:39:19 +00003140/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3141/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3142/// when they refer multiple MIOperands inside a single one.
3143bool ARMAsmParser::
3144cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3145 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3146 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3147
3148 // Create a writeback register dummy placeholder.
3149 Inst.addOperand(MCOperand::CreateImm(0));
3150
3151 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3152 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3153 return true;
3154}
3155
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003156/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3157/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3158/// when they refer multiple MIOperands inside a single one.
3159bool ARMAsmParser::
3160cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3161 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3162 // Create a writeback register dummy placeholder.
3163 Inst.addOperand(MCOperand::CreateImm(0));
3164 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3165 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3166 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3167 return true;
3168}
3169
Jim Grosbach1355cf12011-07-26 17:10:22 +00003170/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003171/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3172/// when they refer multiple MIOperands inside a single one.
3173bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003174cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003175 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3176 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3177
3178 // Create a writeback register dummy placeholder.
3179 Inst.addOperand(MCOperand::CreateImm(0));
3180
Jim Grosbach7ce05792011-08-03 23:50:40 +00003181 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003182 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3183 return true;
3184}
3185
Owen Anderson9ab0f252011-08-26 20:43:14 +00003186/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3187/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3188/// when they refer multiple MIOperands inside a single one.
3189bool ARMAsmParser::
3190cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3191 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3192 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3193
3194 // Create a writeback register dummy placeholder.
3195 Inst.addOperand(MCOperand::CreateImm(0));
3196
3197 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3198 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3199 return true;
3200}
3201
3202
Jim Grosbach548340c2011-08-11 19:22:40 +00003203/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3204/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3205/// when they refer multiple MIOperands inside a single one.
3206bool ARMAsmParser::
3207cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3208 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3209 // Create a writeback register dummy placeholder.
3210 Inst.addOperand(MCOperand::CreateImm(0));
3211 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3212 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3213 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3214 return true;
3215}
3216
Jim Grosbach1355cf12011-07-26 17:10:22 +00003217/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003218/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3219/// when they refer multiple MIOperands inside a single one.
3220bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003221cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003222 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3223 // Create a writeback register dummy placeholder.
3224 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003225 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3226 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3227 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003228 return true;
3229}
3230
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003231/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3232/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3233/// when they refer multiple MIOperands inside a single one.
3234bool ARMAsmParser::
3235cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3236 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3237 // Create a writeback register dummy placeholder.
3238 Inst.addOperand(MCOperand::CreateImm(0));
3239 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3240 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3241 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3242 return true;
3243}
3244
Jim Grosbach7ce05792011-08-03 23:50:40 +00003245/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3246/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3247/// when they refer multiple MIOperands inside a single one.
3248bool ARMAsmParser::
3249cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3250 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3251 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003252 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003253 // Create a writeback register dummy placeholder.
3254 Inst.addOperand(MCOperand::CreateImm(0));
3255 // addr
3256 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3257 // offset
3258 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3259 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003260 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3261 return true;
3262}
3263
Jim Grosbach7ce05792011-08-03 23:50:40 +00003264/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003265/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3266/// when they refer multiple MIOperands inside a single one.
3267bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003268cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3269 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3270 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003271 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003272 // Create a writeback register dummy placeholder.
3273 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003274 // addr
3275 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3276 // offset
3277 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3278 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003279 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3280 return true;
3281}
3282
Jim Grosbach7ce05792011-08-03 23:50:40 +00003283/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003284/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3285/// when they refer multiple MIOperands inside a single one.
3286bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003287cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3288 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003289 // Create a writeback register dummy placeholder.
3290 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003291 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003292 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003293 // addr
3294 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3295 // offset
3296 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3297 // pred
3298 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3299 return true;
3300}
3301
3302/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3303/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3304/// when they refer multiple MIOperands inside a single one.
3305bool ARMAsmParser::
3306cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3307 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3308 // Create a writeback register dummy placeholder.
3309 Inst.addOperand(MCOperand::CreateImm(0));
3310 // Rt
3311 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3312 // addr
3313 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3314 // offset
3315 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3316 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003317 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3318 return true;
3319}
3320
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003321/// cvtLdrdPre - Convert parsed operands to MCInst.
3322/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3323/// when they refer multiple MIOperands inside a single one.
3324bool ARMAsmParser::
3325cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3326 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3327 // Rt, Rt2
3328 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3329 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3330 // Create a writeback register dummy placeholder.
3331 Inst.addOperand(MCOperand::CreateImm(0));
3332 // addr
3333 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3334 // pred
3335 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3336 return true;
3337}
3338
Jim Grosbach14605d12011-08-11 20:28:23 +00003339/// cvtStrdPre - 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::
3343cvtStrdPre(MCInst &Inst, unsigned Opcode,
3344 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3345 // Create a writeback register dummy placeholder.
3346 Inst.addOperand(MCOperand::CreateImm(0));
3347 // Rt, Rt2
3348 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3349 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3350 // addr
3351 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3352 // pred
3353 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3354 return true;
3355}
3356
Jim Grosbach623a4542011-08-10 22:42:16 +00003357/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3358/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3359/// when they refer multiple MIOperands inside a single one.
3360bool ARMAsmParser::
3361cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3362 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3363 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3364 // Create a writeback register dummy placeholder.
3365 Inst.addOperand(MCOperand::CreateImm(0));
3366 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3367 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3368 return true;
3369}
3370
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003371/// cvtThumbMultiple- Convert parsed operands to MCInst.
3372/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3373/// when they refer multiple MIOperands inside a single one.
3374bool ARMAsmParser::
3375cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3376 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3377 // The second source operand must be the same register as the destination
3378 // operand.
3379 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003380 (((ARMOperand*)Operands[3])->getReg() !=
3381 ((ARMOperand*)Operands[5])->getReg()) &&
3382 (((ARMOperand*)Operands[3])->getReg() !=
3383 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003384 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003385 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003386 return false;
3387 }
3388 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3389 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3390 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003391 // If we have a three-operand form, use that, else the second source operand
3392 // is just the destination operand again.
3393 if (Operands.size() == 6)
3394 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3395 else
3396 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003397 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3398
3399 return true;
3400}
Jim Grosbach623a4542011-08-10 22:42:16 +00003401
Jim Grosbach12431322011-10-24 22:16:58 +00003402bool ARMAsmParser::
3403cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3404 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3405 // Vd
3406 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3407 // Create a writeback register dummy placeholder.
3408 Inst.addOperand(MCOperand::CreateImm(0));
3409 // Vn
3410 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3411 // pred
3412 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3413 return true;
3414}
3415
3416bool ARMAsmParser::
3417cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3418 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3419 // Vd
3420 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3421 // Create a writeback register dummy placeholder.
3422 Inst.addOperand(MCOperand::CreateImm(0));
3423 // Vn
3424 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3425 // Vm
3426 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3427 // pred
3428 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3429 return true;
3430}
3431
Bill Wendlinge7176102010-11-06 22:36:58 +00003432/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003433/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003434bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003435parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003436 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003437 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003438 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003439 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003440 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003441
Sean Callanan18b83232010-01-19 21:44:56 +00003442 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003443 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003444 if (BaseRegNum == -1)
3445 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003446
Daniel Dunbar05710932011-01-18 05:34:17 +00003447 // The next token must either be a comma or a closing bracket.
3448 const AsmToken &Tok = Parser.getTok();
3449 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003450 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003451
Jim Grosbach7ce05792011-08-03 23:50:40 +00003452 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003453 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003454 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003455
Jim Grosbach7ce05792011-08-03 23:50:40 +00003456 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003457 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003458
Jim Grosbachfb12f352011-09-19 18:42:21 +00003459 // If there's a pre-indexing writeback marker, '!', just add it as a token
3460 // operand. It's rather odd, but syntactically valid.
3461 if (Parser.getTok().is(AsmToken::Exclaim)) {
3462 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3463 Parser.Lex(); // Eat the '!'.
3464 }
3465
Jim Grosbach7ce05792011-08-03 23:50:40 +00003466 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003467 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003468
Jim Grosbach7ce05792011-08-03 23:50:40 +00003469 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3470 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003471
Jim Grosbach57dcb852011-10-11 17:29:55 +00003472 // If we have a ':', it's an alignment specifier.
3473 if (Parser.getTok().is(AsmToken::Colon)) {
3474 Parser.Lex(); // Eat the ':'.
3475 E = Parser.getTok().getLoc();
3476
3477 const MCExpr *Expr;
3478 if (getParser().ParseExpression(Expr))
3479 return true;
3480
3481 // The expression has to be a constant. Memory references with relocations
3482 // don't come through here, as they use the <label> forms of the relevant
3483 // instructions.
3484 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3485 if (!CE)
3486 return Error (E, "constant expression expected");
3487
3488 unsigned Align = 0;
3489 switch (CE->getValue()) {
3490 default:
3491 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3492 case 64: Align = 8; break;
3493 case 128: Align = 16; break;
3494 case 256: Align = 32; break;
3495 }
3496
3497 // Now we should have the closing ']'
3498 E = Parser.getTok().getLoc();
3499 if (Parser.getTok().isNot(AsmToken::RBrac))
3500 return Error(E, "']' expected");
3501 Parser.Lex(); // Eat right bracket token.
3502
3503 // Don't worry about range checking the value here. That's handled by
3504 // the is*() predicates.
3505 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3506 ARM_AM::no_shift, 0, Align,
3507 false, S, E));
3508
3509 // If there's a pre-indexing writeback marker, '!', just add it as a token
3510 // operand.
3511 if (Parser.getTok().is(AsmToken::Exclaim)) {
3512 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3513 Parser.Lex(); // Eat the '!'.
3514 }
3515
3516 return false;
3517 }
3518
3519 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003520 // offset.
3521 if (Parser.getTok().is(AsmToken::Hash)) {
3522 Parser.Lex(); // Eat the '#'.
3523 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003524
Owen Anderson0da10cf2011-08-29 19:36:44 +00003525 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003526 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003527 if (getParser().ParseExpression(Offset))
3528 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003529
3530 // The expression has to be a constant. Memory references with relocations
3531 // don't come through here, as they use the <label> forms of the relevant
3532 // instructions.
3533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3534 if (!CE)
3535 return Error (E, "constant expression expected");
3536
Owen Anderson0da10cf2011-08-29 19:36:44 +00003537 // If the constant was #-0, represent it as INT32_MIN.
3538 int32_t Val = CE->getValue();
3539 if (isNegative && Val == 0)
3540 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3541
Jim Grosbach7ce05792011-08-03 23:50:40 +00003542 // Now we should have the closing ']'
3543 E = Parser.getTok().getLoc();
3544 if (Parser.getTok().isNot(AsmToken::RBrac))
3545 return Error(E, "']' expected");
3546 Parser.Lex(); // Eat right bracket token.
3547
3548 // Don't worry about range checking the value here. That's handled by
3549 // the is*() predicates.
3550 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003551 ARM_AM::no_shift, 0, 0,
3552 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003553
3554 // If there's a pre-indexing writeback marker, '!', just add it as a token
3555 // operand.
3556 if (Parser.getTok().is(AsmToken::Exclaim)) {
3557 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3558 Parser.Lex(); // Eat the '!'.
3559 }
3560
3561 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003562 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003563
3564 // The register offset is optionally preceded by a '+' or '-'
3565 bool isNegative = false;
3566 if (Parser.getTok().is(AsmToken::Minus)) {
3567 isNegative = true;
3568 Parser.Lex(); // Eat the '-'.
3569 } else if (Parser.getTok().is(AsmToken::Plus)) {
3570 // Nothing to do.
3571 Parser.Lex(); // Eat the '+'.
3572 }
3573
3574 E = Parser.getTok().getLoc();
3575 int OffsetRegNum = tryParseRegister();
3576 if (OffsetRegNum == -1)
3577 return Error(E, "register expected");
3578
3579 // If there's a shift operator, handle it.
3580 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003581 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003582 if (Parser.getTok().is(AsmToken::Comma)) {
3583 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003584 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003585 return true;
3586 }
3587
3588 // Now we should have the closing ']'
3589 E = Parser.getTok().getLoc();
3590 if (Parser.getTok().isNot(AsmToken::RBrac))
3591 return Error(E, "']' expected");
3592 Parser.Lex(); // Eat right bracket token.
3593
3594 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003595 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003596 S, E));
3597
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003598 // If there's a pre-indexing writeback marker, '!', just add it as a token
3599 // operand.
3600 if (Parser.getTok().is(AsmToken::Exclaim)) {
3601 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3602 Parser.Lex(); // Eat the '!'.
3603 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003604
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003605 return false;
3606}
3607
Jim Grosbach7ce05792011-08-03 23:50:40 +00003608/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003609/// ( lsl | lsr | asr | ror ) , # shift_amount
3610/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003611/// return true if it parses a shift otherwise it returns false.
3612bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3613 unsigned &Amount) {
3614 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003615 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003616 if (Tok.isNot(AsmToken::Identifier))
3617 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003618 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003619 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003620 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003621 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003622 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003623 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003624 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003625 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003626 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003627 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003628 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003629 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003630 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003631 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003632
Jim Grosbach7ce05792011-08-03 23:50:40 +00003633 // rrx stands alone.
3634 Amount = 0;
3635 if (St != ARM_AM::rrx) {
3636 Loc = Parser.getTok().getLoc();
3637 // A '#' and a shift amount.
3638 const AsmToken &HashTok = Parser.getTok();
3639 if (HashTok.isNot(AsmToken::Hash))
3640 return Error(HashTok.getLoc(), "'#' expected");
3641 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003642
Jim Grosbach7ce05792011-08-03 23:50:40 +00003643 const MCExpr *Expr;
3644 if (getParser().ParseExpression(Expr))
3645 return true;
3646 // Range check the immediate.
3647 // lsl, ror: 0 <= imm <= 31
3648 // lsr, asr: 0 <= imm <= 32
3649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3650 if (!CE)
3651 return Error(Loc, "shift amount must be an immediate");
3652 int64_t Imm = CE->getValue();
3653 if (Imm < 0 ||
3654 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3655 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3656 return Error(Loc, "immediate shift value out of range");
3657 Amount = Imm;
3658 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003659
3660 return false;
3661}
3662
Jim Grosbach9d390362011-10-03 23:38:36 +00003663/// parseFPImm - A floating point immediate expression operand.
3664ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3665parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3666 SMLoc S = Parser.getTok().getLoc();
3667
3668 if (Parser.getTok().isNot(AsmToken::Hash))
3669 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003670
3671 // Disambiguate the VMOV forms that can accept an FP immediate.
3672 // vmov.f32 <sreg>, #imm
3673 // vmov.f64 <dreg>, #imm
3674 // vmov.f32 <dreg>, #imm @ vector f32x2
3675 // vmov.f32 <qreg>, #imm @ vector f32x4
3676 //
3677 // There are also the NEON VMOV instructions which expect an
3678 // integer constant. Make sure we don't try to parse an FPImm
3679 // for these:
3680 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3681 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3682 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3683 TyOp->getToken() != ".f64"))
3684 return MatchOperand_NoMatch;
3685
Jim Grosbach9d390362011-10-03 23:38:36 +00003686 Parser.Lex(); // Eat the '#'.
3687
3688 // Handle negation, as that still comes through as a separate token.
3689 bool isNegative = false;
3690 if (Parser.getTok().is(AsmToken::Minus)) {
3691 isNegative = true;
3692 Parser.Lex();
3693 }
3694 const AsmToken &Tok = Parser.getTok();
3695 if (Tok.is(AsmToken::Real)) {
3696 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3697 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3698 // If we had a '-' in front, toggle the sign bit.
3699 IntVal ^= (uint64_t)isNegative << 63;
3700 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3701 Parser.Lex(); // Eat the token.
3702 if (Val == -1) {
3703 TokError("floating point value out of range");
3704 return MatchOperand_ParseFail;
3705 }
3706 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3707 return MatchOperand_Success;
3708 }
3709 if (Tok.is(AsmToken::Integer)) {
3710 int64_t Val = Tok.getIntVal();
3711 Parser.Lex(); // Eat the token.
3712 if (Val > 255 || Val < 0) {
3713 TokError("encoded floating point value out of range");
3714 return MatchOperand_ParseFail;
3715 }
3716 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3717 return MatchOperand_Success;
3718 }
3719
3720 TokError("invalid floating point immediate");
3721 return MatchOperand_ParseFail;
3722}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003723/// Parse a arm instruction operand. For now this parses the operand regardless
3724/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003725bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003726 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003727 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003728
3729 // Check if the current operand has a custom associated parser, if so, try to
3730 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003731 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3732 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003733 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003734 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3735 // there was a match, but an error occurred, in which case, just return that
3736 // the operand parsing failed.
3737 if (ResTy == MatchOperand_ParseFail)
3738 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003739
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003740 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003741 default:
3742 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003743 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003744 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003745 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003746 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003747 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003748 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003749 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003750 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003751 else if (Res == -1) // irrecoverable error
3752 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003753 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3754 S = Parser.getTok().getLoc();
3755 Parser.Lex();
3756 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3757 return false;
3758 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003759
3760 // Fall though for the Identifier case that is not a register or a
3761 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003762 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003763 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003764 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3765 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003766 // This was not a register so parse other operands that start with an
3767 // identifier (like labels) as expressions and create them as immediates.
3768 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003769 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003770 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003771 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003772 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003773 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3774 return false;
3775 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003776 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003777 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003778 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003779 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003780 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003781 // #42 -> immediate.
3782 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003783 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003784 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003785 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003786 const MCExpr *ImmVal;
3787 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003788 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003789 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3790 if (!CE) {
3791 Error(S, "constant expression expected");
3792 return MatchOperand_ParseFail;
3793 }
3794 int32_t Val = CE->getValue();
3795 if (isNegative && Val == 0)
3796 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003797 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003798 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3799 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003800 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003801 case AsmToken::Colon: {
3802 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003803 // FIXME: Check it's an expression prefix,
3804 // e.g. (FOO - :lower16:BAR) isn't legal.
3805 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003806 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003807 return true;
3808
Evan Cheng75972122011-01-13 07:58:56 +00003809 const MCExpr *SubExprVal;
3810 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003811 return true;
3812
Evan Cheng75972122011-01-13 07:58:56 +00003813 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3814 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003815 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003816 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003817 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003818 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003819 }
3820}
3821
Jim Grosbach1355cf12011-07-26 17:10:22 +00003822// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003823// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003824bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003825 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003826
3827 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003828 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003829 Parser.Lex(); // Eat ':'
3830
3831 if (getLexer().isNot(AsmToken::Identifier)) {
3832 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3833 return true;
3834 }
3835
3836 StringRef IDVal = Parser.getTok().getIdentifier();
3837 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003838 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003839 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003840 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003841 } else {
3842 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3843 return true;
3844 }
3845 Parser.Lex();
3846
3847 if (getLexer().isNot(AsmToken::Colon)) {
3848 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3849 return true;
3850 }
3851 Parser.Lex(); // Eat the last ':'
3852 return false;
3853}
3854
Daniel Dunbar352e1482011-01-11 15:59:50 +00003855/// \brief Given a mnemonic, split out possible predication code and carry
3856/// setting letters to form a canonical mnemonic and flags.
3857//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003858// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003859// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003860StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003861 unsigned &PredicationCode,
3862 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003863 unsigned &ProcessorIMod,
3864 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003865 PredicationCode = ARMCC::AL;
3866 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003867 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003868
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003869 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003870 //
3871 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003872 if ((Mnemonic == "movs" && isThumb()) ||
3873 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3874 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3875 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3876 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3877 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3878 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3879 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003880 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003881
Jim Grosbach3f00e312011-07-11 17:09:57 +00003882 // First, split out any predication code. Ignore mnemonics we know aren't
3883 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003884 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003885 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003886 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003887 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003888 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3889 .Case("eq", ARMCC::EQ)
3890 .Case("ne", ARMCC::NE)
3891 .Case("hs", ARMCC::HS)
3892 .Case("cs", ARMCC::HS)
3893 .Case("lo", ARMCC::LO)
3894 .Case("cc", ARMCC::LO)
3895 .Case("mi", ARMCC::MI)
3896 .Case("pl", ARMCC::PL)
3897 .Case("vs", ARMCC::VS)
3898 .Case("vc", ARMCC::VC)
3899 .Case("hi", ARMCC::HI)
3900 .Case("ls", ARMCC::LS)
3901 .Case("ge", ARMCC::GE)
3902 .Case("lt", ARMCC::LT)
3903 .Case("gt", ARMCC::GT)
3904 .Case("le", ARMCC::LE)
3905 .Case("al", ARMCC::AL)
3906 .Default(~0U);
3907 if (CC != ~0U) {
3908 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3909 PredicationCode = CC;
3910 }
Bill Wendling52925b62010-10-29 23:50:21 +00003911 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003912
Daniel Dunbar352e1482011-01-11 15:59:50 +00003913 // Next, determine if we have a carry setting bit. We explicitly ignore all
3914 // the instructions we know end in 's'.
3915 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003916 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003917 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3918 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3919 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003920 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3921 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003922 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3923 CarrySetting = true;
3924 }
3925
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003926 // The "cps" instruction can have a interrupt mode operand which is glued into
3927 // the mnemonic. Check if this is the case, split it and parse the imod op
3928 if (Mnemonic.startswith("cps")) {
3929 // Split out any imod code.
3930 unsigned IMod =
3931 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3932 .Case("ie", ARM_PROC::IE)
3933 .Case("id", ARM_PROC::ID)
3934 .Default(~0U);
3935 if (IMod != ~0U) {
3936 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3937 ProcessorIMod = IMod;
3938 }
3939 }
3940
Jim Grosbach89df9962011-08-26 21:43:41 +00003941 // The "it" instruction has the condition mask on the end of the mnemonic.
3942 if (Mnemonic.startswith("it")) {
3943 ITMask = Mnemonic.slice(2, Mnemonic.size());
3944 Mnemonic = Mnemonic.slice(0, 2);
3945 }
3946
Daniel Dunbar352e1482011-01-11 15:59:50 +00003947 return Mnemonic;
3948}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003949
3950/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3951/// inclusion of carry set or predication code operands.
3952//
3953// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003954void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003955getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003956 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003957 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3958 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003959 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003960 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003961 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003962 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003963 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003964 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003965 Mnemonic == "mla" || Mnemonic == "smlal" ||
3966 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003967 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003968 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003969 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003970
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003971 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3972 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3973 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3974 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003975 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3976 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003977 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003978 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3979 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3980 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003981 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3982 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003983 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003984 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003985 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003986 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003987
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003988 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003989 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003990 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003991 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003992 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003993}
3994
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003995bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3996 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003997 // FIXME: This is all horribly hacky. We really need a better way to deal
3998 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003999
4000 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4001 // another does not. Specifically, the MOVW instruction does not. So we
4002 // special case it here and remove the defaulted (non-setting) cc_out
4003 // operand if that's the instruction we're trying to match.
4004 //
4005 // We do this as post-processing of the explicit operands rather than just
4006 // conditionally adding the cc_out in the first place because we need
4007 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004008 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004009 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4010 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4011 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4012 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004013
4014 // Register-register 'add' for thumb does not have a cc_out operand
4015 // when there are only two register operands.
4016 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4017 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4018 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4019 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4020 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004021 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004022 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4023 // have to check the immediate range here since Thumb2 has a variant
4024 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004025 if (((isThumb() && Mnemonic == "add") ||
4026 (isThumbTwo() && Mnemonic == "sub")) &&
4027 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004028 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4029 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4030 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004031 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4032 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4033 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004034 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004035 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4036 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004037 // selecting via the generic "add" mnemonic, so to know that we
4038 // should remove the cc_out operand, we have to explicitly check that
4039 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004040 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4041 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004042 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4043 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4044 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4045 // Nest conditions rather than one big 'if' statement for readability.
4046 //
4047 // If either register is a high reg, it's either one of the SP
4048 // variants (handled above) or a 32-bit encoding, so we just
4049 // check against T3.
4050 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4051 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4052 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4053 return false;
4054 // If both registers are low, we're in an IT block, and the immediate is
4055 // in range, we should use encoding T1 instead, which has a cc_out.
4056 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004057 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004058 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4059 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4060 return false;
4061
4062 // Otherwise, we use encoding T4, which does not have a cc_out
4063 // operand.
4064 return true;
4065 }
4066
Jim Grosbach64944f42011-09-14 21:00:40 +00004067 // The thumb2 multiply instruction doesn't have a CCOut register, so
4068 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4069 // use the 16-bit encoding or not.
4070 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4071 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4072 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4073 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4074 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4075 // If the registers aren't low regs, the destination reg isn't the
4076 // same as one of the source regs, or the cc_out operand is zero
4077 // outside of an IT block, we have to use the 32-bit encoding, so
4078 // remove the cc_out operand.
4079 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4080 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4081 !inITBlock() ||
4082 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4083 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4084 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4085 static_cast<ARMOperand*>(Operands[4])->getReg())))
4086 return true;
4087
4088
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004089
Jim Grosbachf69c8042011-08-24 21:42:27 +00004090 // Register-register 'add/sub' for thumb does not have a cc_out operand
4091 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4092 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4093 // right, this will result in better diagnostics (which operand is off)
4094 // anyway.
4095 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4096 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004097 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4098 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4099 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4100 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004101
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004102 return false;
4103}
4104
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004105/// Parse an arm instruction mnemonic followed by its operands.
4106bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4107 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4108 // Create the leading tokens for the mnemonic, split by '.' characters.
4109 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004110 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004111
Daniel Dunbar352e1482011-01-11 15:59:50 +00004112 // Split out the predication code and carry setting flag from the mnemonic.
4113 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004114 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004115 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004116 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004117 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004118 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004119
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004120 // In Thumb1, only the branch (B) instruction can be predicated.
4121 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4122 Parser.EatToEndOfStatement();
4123 return Error(NameLoc, "conditional execution not supported in Thumb1");
4124 }
4125
Jim Grosbachffa32252011-07-19 19:13:28 +00004126 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4127
Jim Grosbach89df9962011-08-26 21:43:41 +00004128 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4129 // is the mask as it will be for the IT encoding if the conditional
4130 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4131 // where the conditional bit0 is zero, the instruction post-processing
4132 // will adjust the mask accordingly.
4133 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004134 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4135 if (ITMask.size() > 3) {
4136 Parser.EatToEndOfStatement();
4137 return Error(Loc, "too many conditions on IT instruction");
4138 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004139 unsigned Mask = 8;
4140 for (unsigned i = ITMask.size(); i != 0; --i) {
4141 char pos = ITMask[i - 1];
4142 if (pos != 't' && pos != 'e') {
4143 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004144 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004145 }
4146 Mask >>= 1;
4147 if (ITMask[i - 1] == 't')
4148 Mask |= 8;
4149 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004150 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004151 }
4152
Jim Grosbachffa32252011-07-19 19:13:28 +00004153 // FIXME: This is all a pretty gross hack. We should automatically handle
4154 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004155
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004156 // Next, add the CCOut and ConditionCode operands, if needed.
4157 //
4158 // For mnemonics which can ever incorporate a carry setting bit or predication
4159 // code, our matching model involves us always generating CCOut and
4160 // ConditionCode operands to match the mnemonic "as written" and then we let
4161 // the matcher deal with finding the right instruction or generating an
4162 // appropriate error.
4163 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004164 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004165
Jim Grosbach33c16a22011-07-14 22:04:21 +00004166 // If we had a carry-set on an instruction that can't do that, issue an
4167 // error.
4168 if (!CanAcceptCarrySet && CarrySetting) {
4169 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004170 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004171 "' can not set flags, but 's' suffix specified");
4172 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004173 // If we had a predication code on an instruction that can't do that, issue an
4174 // error.
4175 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4176 Parser.EatToEndOfStatement();
4177 return Error(NameLoc, "instruction '" + Mnemonic +
4178 "' is not predicable, but condition code specified");
4179 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004180
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004181 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004182 if (CanAcceptCarrySet) {
4183 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004184 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004185 Loc));
4186 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004187
4188 // Add the predication code operand, if necessary.
4189 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004190 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4191 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004192 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004193 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004194 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004195
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004196 // Add the processor imod operand, if necessary.
4197 if (ProcessorIMod) {
4198 Operands.push_back(ARMOperand::CreateImm(
4199 MCConstantExpr::Create(ProcessorIMod, getContext()),
4200 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004201 }
4202
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004203 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004204 while (Next != StringRef::npos) {
4205 Start = Next;
4206 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004207 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004208
Jim Grosbach4d23e992011-08-24 22:19:48 +00004209 // For now, we're only parsing Thumb1 (for the most part), so
4210 // just ignore ".n" qualifiers. We'll use them to restrict
4211 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00004212 if (ExtraToken != ".n") {
4213 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4214 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4215 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004216 }
4217
4218 // Read the remaining operands.
4219 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004220 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004221 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004222 Parser.EatToEndOfStatement();
4223 return true;
4224 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004225
4226 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004227 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004228
4229 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004230 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004231 Parser.EatToEndOfStatement();
4232 return true;
4233 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004234 }
4235 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004236
Chris Lattnercbf8a982010-09-11 16:18:25 +00004237 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004238 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004239 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004240 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004241 }
Bill Wendling146018f2010-11-06 21:42:12 +00004242
Chris Lattner34e53142010-09-08 05:10:46 +00004243 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004244
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004245 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4246 // do and don't have a cc_out optional-def operand. With some spot-checks
4247 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004248 // parse and adjust accordingly before actually matching. We shouldn't ever
4249 // try to remove a cc_out operand that was explicitly set on the the
4250 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4251 // table driven matcher doesn't fit well with the ARM instruction set.
4252 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004253 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4254 Operands.erase(Operands.begin() + 1);
4255 delete Op;
4256 }
4257
Jim Grosbachcf121c32011-07-28 21:57:55 +00004258 // ARM mode 'blx' need special handling, as the register operand version
4259 // is predicable, but the label operand version is not. So, we can't rely
4260 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004261 // a k_CondCode operand in the list. If we're trying to match the label
4262 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004263 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4264 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4265 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4266 Operands.erase(Operands.begin() + 1);
4267 delete Op;
4268 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004269
4270 // The vector-compare-to-zero instructions have a literal token "#0" at
4271 // the end that comes to here as an immediate operand. Convert it to a
4272 // token to play nicely with the matcher.
4273 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4274 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4275 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4276 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4277 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4278 if (CE && CE->getValue() == 0) {
4279 Operands.erase(Operands.begin() + 5);
4280 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4281 delete Op;
4282 }
4283 }
Jim Grosbach68259142011-10-03 22:30:24 +00004284 // VCMP{E} does the same thing, but with a different operand count.
4285 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4286 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4287 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4288 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4289 if (CE && CE->getValue() == 0) {
4290 Operands.erase(Operands.begin() + 4);
4291 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4292 delete Op;
4293 }
4294 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004295 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4296 // end. Convert it to a token here.
4297 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4298 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4299 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4300 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4301 if (CE && CE->getValue() == 0) {
4302 Operands.erase(Operands.begin() + 5);
4303 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4304 delete Op;
4305 }
4306 }
4307
Chris Lattner98986712010-01-14 22:21:20 +00004308 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004309}
4310
Jim Grosbach189610f2011-07-26 18:25:39 +00004311// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004312
4313// return 'true' if register list contains non-low GPR registers,
4314// 'false' otherwise. If Reg is in the register list or is HiReg, set
4315// 'containsReg' to true.
4316static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4317 unsigned HiReg, bool &containsReg) {
4318 containsReg = false;
4319 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4320 unsigned OpReg = Inst.getOperand(i).getReg();
4321 if (OpReg == Reg)
4322 containsReg = true;
4323 // Anything other than a low register isn't legal here.
4324 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4325 return true;
4326 }
4327 return false;
4328}
4329
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004330// Check if the specified regisgter is in the register list of the inst,
4331// starting at the indicated operand number.
4332static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4333 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4334 unsigned OpReg = Inst.getOperand(i).getReg();
4335 if (OpReg == Reg)
4336 return true;
4337 }
4338 return false;
4339}
4340
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004341// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4342// the ARMInsts array) instead. Getting that here requires awkward
4343// API changes, though. Better way?
4344namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004345extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004346}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004347static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004348 return ARMInsts[Opcode];
4349}
4350
Jim Grosbach189610f2011-07-26 18:25:39 +00004351// FIXME: We would really like to be able to tablegen'erate this.
4352bool ARMAsmParser::
4353validateInstruction(MCInst &Inst,
4354 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004355 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004356 SMLoc Loc = Operands[0]->getStartLoc();
4357 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004358 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4359 // being allowed in IT blocks, but not being predicable. It just always
4360 // executes.
4361 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004362 unsigned bit = 1;
4363 if (ITState.FirstCond)
4364 ITState.FirstCond = false;
4365 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004366 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004367 // The instruction must be predicable.
4368 if (!MCID.isPredicable())
4369 return Error(Loc, "instructions in IT block must be predicable");
4370 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4371 unsigned ITCond = bit ? ITState.Cond :
4372 ARMCC::getOppositeCondition(ITState.Cond);
4373 if (Cond != ITCond) {
4374 // Find the condition code Operand to get its SMLoc information.
4375 SMLoc CondLoc;
4376 for (unsigned i = 1; i < Operands.size(); ++i)
4377 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4378 CondLoc = Operands[i]->getStartLoc();
4379 return Error(CondLoc, "incorrect condition in IT block; got '" +
4380 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4381 "', but expected '" +
4382 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4383 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004384 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004385 } else if (isThumbTwo() && MCID.isPredicable() &&
4386 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004387 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4388 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004389 return Error(Loc, "predicated instructions must be in IT block");
4390
Jim Grosbach189610f2011-07-26 18:25:39 +00004391 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004392 case ARM::LDRD:
4393 case ARM::LDRD_PRE:
4394 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004395 case ARM::LDREXD: {
4396 // Rt2 must be Rt + 1.
4397 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4398 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4399 if (Rt2 != Rt + 1)
4400 return Error(Operands[3]->getStartLoc(),
4401 "destination operands must be sequential");
4402 return false;
4403 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004404 case ARM::STRD: {
4405 // Rt2 must be Rt + 1.
4406 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4407 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4408 if (Rt2 != Rt + 1)
4409 return Error(Operands[3]->getStartLoc(),
4410 "source operands must be sequential");
4411 return false;
4412 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004413 case ARM::STRD_PRE:
4414 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004415 case ARM::STREXD: {
4416 // Rt2 must be Rt + 1.
4417 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4418 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4419 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004420 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004421 "source operands must be sequential");
4422 return false;
4423 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004424 case ARM::SBFX:
4425 case ARM::UBFX: {
4426 // width must be in range [1, 32-lsb]
4427 unsigned lsb = Inst.getOperand(2).getImm();
4428 unsigned widthm1 = Inst.getOperand(3).getImm();
4429 if (widthm1 >= 32 - lsb)
4430 return Error(Operands[5]->getStartLoc(),
4431 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004432 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004433 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004434 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004435 // If we're parsing Thumb2, the .w variant is available and handles
4436 // most cases that are normally illegal for a Thumb1 LDM
4437 // instruction. We'll make the transformation in processInstruction()
4438 // if necessary.
4439 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004440 // Thumb LDM instructions are writeback iff the base register is not
4441 // in the register list.
4442 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004443 bool hasWritebackToken =
4444 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4445 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004446 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004447 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004448 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4449 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004450 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004451 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004452 return Error(Operands[2]->getStartLoc(),
4453 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004454 // If we should not have writeback, there must not be a '!'. This is
4455 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004456 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004457 return Error(Operands[3]->getStartLoc(),
4458 "writeback operator '!' not allowed when base register "
4459 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004460
4461 break;
4462 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004463 case ARM::t2LDMIA_UPD: {
4464 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4465 return Error(Operands[4]->getStartLoc(),
4466 "writeback operator '!' not allowed when base register "
4467 "in register list");
4468 break;
4469 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004470 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004471 bool listContainsBase;
4472 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4473 return Error(Operands[2]->getStartLoc(),
4474 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004475 break;
4476 }
4477 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004478 bool listContainsBase;
4479 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4480 return Error(Operands[2]->getStartLoc(),
4481 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004482 break;
4483 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004484 case ARM::tSTMIA_UPD: {
4485 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004486 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004487 return Error(Operands[4]->getStartLoc(),
4488 "registers must be in range r0-r7");
4489 break;
4490 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004491 }
4492
4493 return false;
4494}
4495
Jim Grosbachf8fce712011-08-11 17:35:48 +00004496void ARMAsmParser::
4497processInstruction(MCInst &Inst,
4498 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4499 switch (Inst.getOpcode()) {
4500 case ARM::LDMIA_UPD:
4501 // If this is a load of a single register via a 'pop', then we should use
4502 // a post-indexed LDR instruction instead, per the ARM ARM.
4503 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4504 Inst.getNumOperands() == 5) {
4505 MCInst TmpInst;
4506 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4507 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4508 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4509 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4510 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4511 TmpInst.addOperand(MCOperand::CreateImm(4));
4512 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4513 TmpInst.addOperand(Inst.getOperand(3));
4514 Inst = TmpInst;
4515 }
4516 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004517 case ARM::STMDB_UPD:
4518 // If this is a store of a single register via a 'push', then we should use
4519 // a pre-indexed STR instruction instead, per the ARM ARM.
4520 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4521 Inst.getNumOperands() == 5) {
4522 MCInst TmpInst;
4523 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4524 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4525 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4526 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4527 TmpInst.addOperand(MCOperand::CreateImm(-4));
4528 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4529 TmpInst.addOperand(Inst.getOperand(3));
4530 Inst = TmpInst;
4531 }
4532 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004533 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004534 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4535 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4536 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4537 // to encoding T1 if <Rd> is omitted."
4538 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004539 Inst.setOpcode(ARM::tADDi3);
4540 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004541 case ARM::tSUBi8:
4542 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4543 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4544 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4545 // to encoding T1 if <Rd> is omitted."
4546 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4547 Inst.setOpcode(ARM::tSUBi3);
4548 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004549 case ARM::tB:
4550 // A Thumb conditional branch outside of an IT block is a tBcc.
4551 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4552 Inst.setOpcode(ARM::tBcc);
4553 break;
4554 case ARM::t2B:
4555 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4556 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4557 Inst.setOpcode(ARM::t2Bcc);
4558 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004559 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004560 // If the conditional is AL or we're in an IT block, we really want t2B.
4561 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004562 Inst.setOpcode(ARM::t2B);
4563 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004564 case ARM::tBcc:
4565 // If the conditional is AL, we really want tB.
4566 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4567 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004568 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004569 case ARM::tLDMIA: {
4570 // If the register list contains any high registers, or if the writeback
4571 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4572 // instead if we're in Thumb2. Otherwise, this should have generated
4573 // an error in validateInstruction().
4574 unsigned Rn = Inst.getOperand(0).getReg();
4575 bool hasWritebackToken =
4576 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4577 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4578 bool listContainsBase;
4579 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4580 (!listContainsBase && !hasWritebackToken) ||
4581 (listContainsBase && hasWritebackToken)) {
4582 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4583 assert (isThumbTwo());
4584 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4585 // If we're switching to the updating version, we need to insert
4586 // the writeback tied operand.
4587 if (hasWritebackToken)
4588 Inst.insert(Inst.begin(),
4589 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4590 }
4591 break;
4592 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004593 case ARM::tSTMIA_UPD: {
4594 // If the register list contains any high registers, we need to use
4595 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4596 // should have generated an error in validateInstruction().
4597 unsigned Rn = Inst.getOperand(0).getReg();
4598 bool listContainsBase;
4599 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4600 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4601 assert (isThumbTwo());
4602 Inst.setOpcode(ARM::t2STMIA_UPD);
4603 }
4604 break;
4605 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004606 case ARM::t2MOVi: {
4607 // If we can use the 16-bit encoding and the user didn't explicitly
4608 // request the 32-bit variant, transform it here.
4609 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4610 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004611 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4612 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4613 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004614 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4615 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4616 // The operands aren't in the same order for tMOVi8...
4617 MCInst TmpInst;
4618 TmpInst.setOpcode(ARM::tMOVi8);
4619 TmpInst.addOperand(Inst.getOperand(0));
4620 TmpInst.addOperand(Inst.getOperand(4));
4621 TmpInst.addOperand(Inst.getOperand(1));
4622 TmpInst.addOperand(Inst.getOperand(2));
4623 TmpInst.addOperand(Inst.getOperand(3));
4624 Inst = TmpInst;
4625 }
4626 break;
4627 }
4628 case ARM::t2MOVr: {
4629 // If we can use the 16-bit encoding and the user didn't explicitly
4630 // request the 32-bit variant, transform it here.
4631 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4632 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4633 Inst.getOperand(2).getImm() == ARMCC::AL &&
4634 Inst.getOperand(4).getReg() == ARM::CPSR &&
4635 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4636 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4637 // The operands aren't the same for tMOV[S]r... (no cc_out)
4638 MCInst TmpInst;
4639 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4640 TmpInst.addOperand(Inst.getOperand(0));
4641 TmpInst.addOperand(Inst.getOperand(1));
4642 TmpInst.addOperand(Inst.getOperand(2));
4643 TmpInst.addOperand(Inst.getOperand(3));
4644 Inst = TmpInst;
4645 }
4646 break;
4647 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004648 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004649 case ARM::t2SXTB:
4650 case ARM::t2UXTH:
4651 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004652 // If we can use the 16-bit encoding and the user didn't explicitly
4653 // request the 32-bit variant, transform it here.
4654 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4655 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4656 Inst.getOperand(2).getImm() == 0 &&
4657 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4658 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004659 unsigned NewOpc;
4660 switch (Inst.getOpcode()) {
4661 default: llvm_unreachable("Illegal opcode!");
4662 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4663 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4664 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4665 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4666 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004667 // The operands aren't the same for thumb1 (no rotate operand).
4668 MCInst TmpInst;
4669 TmpInst.setOpcode(NewOpc);
4670 TmpInst.addOperand(Inst.getOperand(0));
4671 TmpInst.addOperand(Inst.getOperand(1));
4672 TmpInst.addOperand(Inst.getOperand(3));
4673 TmpInst.addOperand(Inst.getOperand(4));
4674 Inst = TmpInst;
4675 }
4676 break;
4677 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004678 case ARM::t2IT: {
4679 // The mask bits for all but the first condition are represented as
4680 // the low bit of the condition code value implies 't'. We currently
4681 // always have 1 implies 't', so XOR toggle the bits if the low bit
4682 // of the condition code is zero. The encoding also expects the low
4683 // bit of the condition to be encoded as bit 4 of the mask operand,
4684 // so mask that in if needed
4685 MCOperand &MO = Inst.getOperand(1);
4686 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004687 unsigned OrigMask = Mask;
4688 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004689 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004690 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4691 for (unsigned i = 3; i != TZ; --i)
4692 Mask ^= 1 << i;
4693 } else
4694 Mask |= 0x10;
4695 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004696
4697 // Set up the IT block state according to the IT instruction we just
4698 // matched.
4699 assert(!inITBlock() && "nested IT blocks?!");
4700 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4701 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4702 ITState.CurPosition = 0;
4703 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004704 break;
4705 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004706 }
4707}
4708
Jim Grosbach47a0d522011-08-16 20:45:50 +00004709unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4710 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4711 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004712 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004713 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004714 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4715 assert(MCID.hasOptionalDef() &&
4716 "optionally flag setting instruction missing optional def operand");
4717 assert(MCID.NumOperands == Inst.getNumOperands() &&
4718 "operand count mismatch!");
4719 // Find the optional-def operand (cc_out).
4720 unsigned OpNo;
4721 for (OpNo = 0;
4722 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4723 ++OpNo)
4724 ;
4725 // If we're parsing Thumb1, reject it completely.
4726 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4727 return Match_MnemonicFail;
4728 // If we're parsing Thumb2, which form is legal depends on whether we're
4729 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004730 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4731 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004732 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004733 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4734 inITBlock())
4735 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004736 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004737 // Some high-register supporting Thumb1 encodings only allow both registers
4738 // to be from r0-r7 when in Thumb2.
4739 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4740 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4741 isARMLowRegister(Inst.getOperand(2).getReg()))
4742 return Match_RequiresThumb2;
4743 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004744 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004745 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4746 isARMLowRegister(Inst.getOperand(1).getReg()))
4747 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004748 return Match_Success;
4749}
4750
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004751bool ARMAsmParser::
4752MatchAndEmitInstruction(SMLoc IDLoc,
4753 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4754 MCStreamer &Out) {
4755 MCInst Inst;
4756 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004757 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004758 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004759 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004760 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004761 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004762 // Context sensitive operand constraints aren't handled by the matcher,
4763 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004764 if (validateInstruction(Inst, Operands)) {
4765 // Still progress the IT block, otherwise one wrong condition causes
4766 // nasty cascading errors.
4767 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004768 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004769 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004770
Jim Grosbachf8fce712011-08-11 17:35:48 +00004771 // Some instructions need post-processing to, for example, tweak which
4772 // encoding is selected.
4773 processInstruction(Inst, Operands);
4774
Jim Grosbacha1109882011-09-02 23:22:08 +00004775 // Only move forward at the very end so that everything in validate
4776 // and process gets a consistent answer about whether we're in an IT
4777 // block.
4778 forwardITPosition();
4779
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004780 Out.EmitInstruction(Inst);
4781 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004782 case Match_MissingFeature:
4783 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4784 return true;
4785 case Match_InvalidOperand: {
4786 SMLoc ErrorLoc = IDLoc;
4787 if (ErrorInfo != ~0U) {
4788 if (ErrorInfo >= Operands.size())
4789 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004790
Chris Lattnere73d4f82010-10-28 21:41:58 +00004791 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4792 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4793 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004794
Chris Lattnere73d4f82010-10-28 21:41:58 +00004795 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004796 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004797 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004798 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004799 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004800 // The converter function will have already emited a diagnostic.
4801 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004802 case Match_RequiresNotITBlock:
4803 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004804 case Match_RequiresITBlock:
4805 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004806 case Match_RequiresV6:
4807 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4808 case Match_RequiresThumb2:
4809 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004810 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004811
Eric Christopherc223e2b2010-10-29 09:26:59 +00004812 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004813 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004814}
4815
Jim Grosbach1355cf12011-07-26 17:10:22 +00004816/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004817bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4818 StringRef IDVal = DirectiveID.getIdentifier();
4819 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004820 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004821 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004822 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004823 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004824 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004825 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004826 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004827 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004828 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004829 return true;
4830}
4831
Jim Grosbach1355cf12011-07-26 17:10:22 +00004832/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004833/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004834bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004835 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4836 for (;;) {
4837 const MCExpr *Value;
4838 if (getParser().ParseExpression(Value))
4839 return true;
4840
Chris Lattneraaec2052010-01-19 19:46:13 +00004841 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004842
4843 if (getLexer().is(AsmToken::EndOfStatement))
4844 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004845
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004846 // FIXME: Improve diagnostic.
4847 if (getLexer().isNot(AsmToken::Comma))
4848 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004849 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004850 }
4851 }
4852
Sean Callananb9a25b72010-01-19 20:27:46 +00004853 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004854 return false;
4855}
4856
Jim Grosbach1355cf12011-07-26 17:10:22 +00004857/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004858/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004859bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004860 if (getLexer().isNot(AsmToken::EndOfStatement))
4861 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004862 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004863
4864 // TODO: set thumb mode
4865 // TODO: tell the MC streamer the mode
4866 // getParser().getStreamer().Emit???();
4867 return false;
4868}
4869
Jim Grosbach1355cf12011-07-26 17:10:22 +00004870/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004871/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004872bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004873 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4874 bool isMachO = MAI.hasSubsectionsViaSymbols();
4875 StringRef Name;
4876
4877 // Darwin asm has function name after .thumb_func direction
4878 // ELF doesn't
4879 if (isMachO) {
4880 const AsmToken &Tok = Parser.getTok();
4881 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4882 return Error(L, "unexpected token in .thumb_func directive");
4883 Name = Tok.getString();
4884 Parser.Lex(); // Consume the identifier token.
4885 }
4886
Kevin Enderby515d5092009-10-15 20:48:48 +00004887 if (getLexer().isNot(AsmToken::EndOfStatement))
4888 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004889 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004890
Rafael Espindola64695402011-05-16 16:17:21 +00004891 // FIXME: assuming function name will be the line following .thumb_func
4892 if (!isMachO) {
4893 Name = Parser.getTok().getString();
4894 }
4895
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004896 // Mark symbol as a thumb symbol.
4897 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4898 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004899 return false;
4900}
4901
Jim Grosbach1355cf12011-07-26 17:10:22 +00004902/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004903/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004904bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004905 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004906 if (Tok.isNot(AsmToken::Identifier))
4907 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004908 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004909 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004910 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004911 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004912 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004913 else
4914 return Error(L, "unrecognized syntax mode in .syntax directive");
4915
4916 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004917 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004918 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004919
4920 // TODO tell the MC streamer the mode
4921 // getParser().getStreamer().Emit???();
4922 return false;
4923}
4924
Jim Grosbach1355cf12011-07-26 17:10:22 +00004925/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004926/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004927bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004928 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004929 if (Tok.isNot(AsmToken::Integer))
4930 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004931 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004932 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004933 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004934 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004935 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004936 else
4937 return Error(L, "invalid operand to .code directive");
4938
4939 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004940 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004941 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004942
Evan Cheng32869202011-07-08 22:36:29 +00004943 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004944 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004945 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004946 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004947 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004948 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004949 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004950 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004951 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004952
Kevin Enderby515d5092009-10-15 20:48:48 +00004953 return false;
4954}
4955
Sean Callanan90b70972010-04-07 20:29:34 +00004956extern "C" void LLVMInitializeARMAsmLexer();
4957
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004958/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004959extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004960 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4961 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004962 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004963}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004964
Chris Lattner0692ee62010-09-06 19:11:01 +00004965#define GET_REGISTER_MATCHER
4966#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004967#include "ARMGenAsmMatcher.inc"