blob: afb6e5684dd796e2f648497c8c057ec413754ee2 [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 Grosbach43904292011-07-25 20:14:50 +0000141 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000143 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000147 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
148 StringRef Op, int Low, int High);
149 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
150 return parsePKHImm(O, "lsl", 0, 31);
151 }
152 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
153 return parsePKHImm(O, "asr", 1, 32);
154 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000155 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000156 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000157 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000158 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000159 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000160 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000161 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000162
163 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000164 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
165 const SmallVectorImpl<MCParsedAsmOperand*> &);
166 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000168 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000170 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000172 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000174 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000176 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000178 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000180 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000182 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
184 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000190 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000192 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000194 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000196 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000198
199 bool validateInstruction(MCInst &Inst,
200 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000201 void processInstruction(MCInst &Inst,
202 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000203 bool shouldOmitCCOutOperand(StringRef Mnemonic,
204 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000205
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000206public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000207 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000208 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000209 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000210 Match_RequiresV6,
211 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000212 };
213
Evan Chengffc0e732011-07-09 05:47:46 +0000214 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000215 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000216 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000217
Evan Chengebdeeab2011-07-08 01:53:10 +0000218 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000219 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000220
221 // Not in an ITBlock to start with.
222 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000223 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000224
Jim Grosbach1355cf12011-07-26 17:10:22 +0000225 // Implementation of the MCTargetAsmParser interface:
226 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
227 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000228 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000229 bool ParseDirective(AsmToken DirectiveID);
230
Jim Grosbach47a0d522011-08-16 20:45:50 +0000231 unsigned checkTargetMatchPredicate(MCInst &Inst);
232
Jim Grosbach1355cf12011-07-26 17:10:22 +0000233 bool MatchAndEmitInstruction(SMLoc IDLoc,
234 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
235 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000236};
Jim Grosbach16c74252010-10-29 14:46:02 +0000237} // end anonymous namespace
238
Chris Lattner3a697562010-10-28 17:20:03 +0000239namespace {
240
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000241/// ARMOperand - Instances of this class represent a parsed ARM machine
242/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000243class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000244 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000245 k_CondCode,
246 k_CCOut,
247 k_ITCondMask,
248 k_CoprocNum,
249 k_CoprocReg,
250 k_Immediate,
251 k_FPImmediate,
252 k_MemBarrierOpt,
253 k_Memory,
254 k_PostIndexRegister,
255 k_MSRMask,
256 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000257 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000258 k_Register,
259 k_RegisterList,
260 k_DPRRegisterList,
261 k_SPRRegisterList,
262 k_ShiftedRegister,
263 k_ShiftedImmediate,
264 k_ShifterImmediate,
265 k_RotateImmediate,
266 k_BitfieldDescriptor,
267 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000268 } Kind;
269
Sean Callanan76264762010-04-02 22:27:05 +0000270 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000271 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000272
273 union {
274 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000275 ARMCC::CondCodes Val;
276 } CC;
277
278 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000279 unsigned Val;
280 } Cop;
281
282 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000283 unsigned Mask:4;
284 } ITMask;
285
286 struct {
287 ARM_MB::MemBOpt Val;
288 } MBOpt;
289
290 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000291 ARM_PROC::IFlags Val;
292 } IFlags;
293
294 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000295 unsigned Val;
296 } MMask;
297
298 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000299 const char *Data;
300 unsigned Length;
301 } Tok;
302
303 struct {
304 unsigned RegNum;
305 } Reg;
306
Bill Wendling8155e5b2010-11-06 22:19:43 +0000307 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000308 unsigned Val;
309 } VectorIndex;
310
311 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000312 const MCExpr *Val;
313 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000314
Jim Grosbach9d390362011-10-03 23:38:36 +0000315 struct {
316 unsigned Val; // encoded 8-bit representation
317 } FPImm;
318
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000319 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000320 struct {
321 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000322 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
323 // was specified.
324 const MCConstantExpr *OffsetImm; // Offset immediate value
325 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
326 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000327 unsigned ShiftImm; // shift for OffsetReg.
328 unsigned Alignment; // 0 = no alignment specified
329 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000330 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000331 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000332
333 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000334 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000335 bool isAdd;
336 ARM_AM::ShiftOpc ShiftTy;
337 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000338 } PostIdxReg;
339
340 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000341 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000342 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000343 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000344 struct {
345 ARM_AM::ShiftOpc ShiftTy;
346 unsigned SrcReg;
347 unsigned ShiftReg;
348 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000349 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000350 struct {
351 ARM_AM::ShiftOpc ShiftTy;
352 unsigned SrcReg;
353 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000354 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000355 struct {
356 unsigned Imm;
357 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000358 struct {
359 unsigned LSB;
360 unsigned Width;
361 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000362 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000363
Bill Wendling146018f2010-11-06 21:42:12 +0000364 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
365public:
Sean Callanan76264762010-04-02 22:27:05 +0000366 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
367 Kind = o.Kind;
368 StartLoc = o.StartLoc;
369 EndLoc = o.EndLoc;
370 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000371 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000372 CC = o.CC;
373 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000374 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000375 ITMask = o.ITMask;
376 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000377 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000378 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000379 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000380 case k_CCOut:
381 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000382 Reg = o.Reg;
383 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000384 case k_RegisterList:
385 case k_DPRRegisterList:
386 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000387 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000388 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000389 case k_CoprocNum:
390 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000391 Cop = o.Cop;
392 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000393 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000394 Imm = o.Imm;
395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000397 FPImm = o.FPImm;
398 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000400 MBOpt = o.MBOpt;
401 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000402 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000403 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000404 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000405 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000406 PostIdxReg = o.PostIdxReg;
407 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000409 MMask = o.MMask;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000412 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000415 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000416 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000417 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000418 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000419 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000420 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000421 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000422 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000423 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000424 RotImm = o.RotImm;
425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000427 Bitfield = o.Bitfield;
428 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000429 case k_VectorIndex:
430 VectorIndex = o.VectorIndex;
431 break;
Sean Callanan76264762010-04-02 22:27:05 +0000432 }
433 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000434
Sean Callanan76264762010-04-02 22:27:05 +0000435 /// getStartLoc - Get the location of the first token of this operand.
436 SMLoc getStartLoc() const { return StartLoc; }
437 /// getEndLoc - Get the location of the last token of this operand.
438 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000439
Daniel Dunbar8462b302010-08-11 06:36:53 +0000440 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000442 return CC.Val;
443 }
444
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000445 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000446 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000447 return Cop.Val;
448 }
449
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000450 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000452 return StringRef(Tok.Data, Tok.Length);
453 }
454
455 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000457 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000458 }
459
Bill Wendling5fa22a12010-11-09 23:28:44 +0000460 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
462 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000463 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000464 }
465
Kevin Enderbycfe07242009-10-13 22:19:02 +0000466 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000467 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000468 return Imm.Val;
469 }
470
Jim Grosbach9d390362011-10-03 23:38:36 +0000471 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000472 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000473 return FPImm.Val;
474 }
475
Jim Grosbach460a9052011-10-07 23:56:00 +0000476 unsigned getVectorIndex() const {
477 assert(Kind == k_VectorIndex && "Invalid access!");
478 return VectorIndex.Val;
479 }
480
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000481 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000483 return MBOpt.Val;
484 }
485
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000486 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000487 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000488 return IFlags.Val;
489 }
490
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000491 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000493 return MMask.Val;
494 }
495
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000496 bool isCoprocNum() const { return Kind == k_CoprocNum; }
497 bool isCoprocReg() const { return Kind == k_CoprocReg; }
498 bool isCondCode() const { return Kind == k_CondCode; }
499 bool isCCOut() const { return Kind == k_CCOut; }
500 bool isITMask() const { return Kind == k_ITCondMask; }
501 bool isITCondCode() const { return Kind == k_CondCode; }
502 bool isImm() const { return Kind == k_Immediate; }
503 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000504 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000505 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000506 return false;
507 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
508 if (!CE) return false;
509 int64_t Value = CE->getValue();
510 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
511 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000512 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000513 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000514 return false;
515 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
516 if (!CE) return false;
517 int64_t Value = CE->getValue();
518 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
519 }
520 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000521 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000522 return false;
523 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
524 if (!CE) return false;
525 int64_t Value = CE->getValue();
526 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
527 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000528 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000529 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000530 return false;
531 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
532 if (!CE) return false;
533 int64_t Value = CE->getValue();
534 return Value >= 0 && Value < 256;
535 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000536 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000537 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000538 return false;
539 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
540 if (!CE) return false;
541 int64_t Value = CE->getValue();
542 return Value >= 0 && Value < 8;
543 }
544 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000545 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000546 return false;
547 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
548 if (!CE) return false;
549 int64_t Value = CE->getValue();
550 return Value >= 0 && Value < 16;
551 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000552 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000553 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000554 return false;
555 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
556 if (!CE) return false;
557 int64_t Value = CE->getValue();
558 return Value >= 0 && Value < 32;
559 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000560 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000561 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000562 return false;
563 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
564 if (!CE) return false;
565 int64_t Value = CE->getValue();
566 return Value > 0 && Value < 17;
567 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000568 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000569 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000570 return false;
571 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
572 if (!CE) return false;
573 int64_t Value = CE->getValue();
574 return Value > 0 && Value < 33;
575 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000576 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000577 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000578 return false;
579 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
580 if (!CE) return false;
581 int64_t Value = CE->getValue();
582 return Value >= 0 && Value < 65536;
583 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000584 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000585 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000586 return false;
587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 // If it's not a constant expression, it'll generate a fixup and be
589 // handled later.
590 if (!CE) return true;
591 int64_t Value = CE->getValue();
592 return Value >= 0 && Value < 65536;
593 }
Jim Grosbached838482011-07-26 16:24:27 +0000594 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000595 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +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 <= 0xffffff;
601 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000602 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000603 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +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 < 33;
609 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000610 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000611 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000612 return false;
613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
614 if (!CE) return false;
615 int64_t Value = CE->getValue();
616 return Value >= 0 && Value < 32;
617 }
618 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000619 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000620 return false;
621 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
622 if (!CE) return false;
623 int64_t Value = CE->getValue();
624 return Value > 0 && Value <= 32;
625 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000626 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000627 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000628 return false;
629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return ARM_AM::getSOImmVal(Value) != -1;
633 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000634 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000635 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000636 return false;
637 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
638 if (!CE) return false;
639 int64_t Value = CE->getValue();
640 return ARM_AM::getT2SOImmVal(Value) != -1;
641 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000642 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000643 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000644 return false;
645 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
646 if (!CE) return false;
647 int64_t Value = CE->getValue();
648 return Value == 1 || Value == 0;
649 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000650 bool isReg() const { return Kind == k_Register; }
651 bool isRegList() const { return Kind == k_RegisterList; }
652 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
653 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
654 bool isToken() const { return Kind == k_Token; }
655 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
656 bool isMemory() const { return Kind == k_Memory; }
657 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
658 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
659 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
660 bool isRotImm() const { return Kind == k_RotateImmediate; }
661 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
662 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000663 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000664 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000665 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000666 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000667 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000668 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000669 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000670 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
671 (alignOK || Memory.Alignment == 0);
672 }
673 bool isAlignedMemory() const {
674 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000675 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000676 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000677 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000678 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000679 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000680 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000681 if (!Memory.OffsetImm) return true;
682 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000683 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000684 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000685 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000686 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000687 return false;
688 // Immediate offset in range [-4095, 4095].
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Val = CE->getValue();
692 return Val > -4096 && Val < 4096;
693 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000694 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000695 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000696 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000697 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000698 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000699 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000700 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000701 if (!Memory.OffsetImm) return true;
702 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000703 return Val > -256 && Val < 256;
704 }
705 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000706 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000707 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000708 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000709 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
710 // Immediate offset in range [-255, 255].
711 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
712 if (!CE) return false;
713 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000714 // Special case, #-0 is INT32_MIN.
715 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000716 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000717 bool isAddrMode5() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000718 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000719 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000720 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000721 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000722 if (!Memory.OffsetImm) return true;
723 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000724 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
725 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000726 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000727 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000728 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000729 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000730 return false;
731 return true;
732 }
733 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000734 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000735 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
736 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000737 return false;
738 return true;
739 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000740 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000741 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000742 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000743 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000744 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000745 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000746 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
747 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000748 return false;
749 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000750 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000751 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000752 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000753 return false;
754 return true;
755 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000756 bool isMemThumbRR() const {
757 // Thumb reg+reg addressing is simple. Just two registers, a base and
758 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000759 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000760 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000761 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000762 return isARMLowRegister(Memory.BaseRegNum) &&
763 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000764 }
765 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000766 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000767 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000768 return false;
769 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000770 if (!Memory.OffsetImm) return true;
771 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000772 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
773 }
Jim Grosbach38466302011-08-19 18:55:51 +0000774 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000775 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000776 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000777 return false;
778 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000779 if (!Memory.OffsetImm) return true;
780 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000781 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
782 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000783 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000784 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000785 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000786 return false;
787 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000788 if (!Memory.OffsetImm) return true;
789 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000790 return Val >= 0 && Val <= 31;
791 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000792 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000793 if (!isMemory() || Memory.OffsetRegNum != 0 ||
794 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000795 return false;
796 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000797 if (!Memory.OffsetImm) return true;
798 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000799 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000800 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000801 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000802 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000803 return false;
804 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000805 if (!Memory.OffsetImm) return true;
806 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000807 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
808 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000809 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000810 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000811 return false;
812 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000813 if (!Memory.OffsetImm) return true;
814 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000815 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
816 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000817 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000818 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000819 return false;
820 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000821 if (!Memory.OffsetImm) return true;
822 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000823 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000824 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000825 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000826 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000827 return false;
828 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000829 if (!Memory.OffsetImm) return true;
830 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000831 return Val >= 0 && Val < 256;
832 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000833 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000834 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000835 return false;
836 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000837 if (!Memory.OffsetImm) return true;
838 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000839 return Val > -256 && Val < 0;
840 }
841 bool isMemUImm12Offset() const {
842 // If we have an immediate that's not a constant, treat it as a label
843 // reference needing a fixup. If it is a constant, it's something else
844 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000845 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000846 return true;
847
Jim Grosbach57dcb852011-10-11 17:29:55 +0000848 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000849 return false;
850 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (!Memory.OffsetImm) return true;
852 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000853 return (Val >= 0 && Val < 4096);
854 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000855 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000856 // If we have an immediate that's not a constant, treat it as a label
857 // reference needing a fixup. If it is a constant, it's something else
858 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000859 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000860 return true;
861
Jim Grosbach57dcb852011-10-11 17:29:55 +0000862 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000863 return false;
864 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000865 if (!Memory.OffsetImm) return true;
866 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000867 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 }
869 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000870 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000871 return false;
872 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
873 if (!CE) return false;
874 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000875 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000876 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000877 bool isPostIdxImm8s4() const {
878 if (Kind != k_Immediate)
879 return false;
880 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
881 if (!CE) return false;
882 int64_t Val = CE->getValue();
883 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
884 (Val == INT32_MIN);
885 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000886
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000887 bool isMSRMask() const { return Kind == k_MSRMask; }
888 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000889
Jim Grosbach460a9052011-10-07 23:56:00 +0000890 bool isVectorIndex8() const {
891 if (Kind != k_VectorIndex) return false;
892 return VectorIndex.Val < 8;
893 }
894 bool isVectorIndex16() const {
895 if (Kind != k_VectorIndex) return false;
896 return VectorIndex.Val < 4;
897 }
898 bool isVectorIndex32() const {
899 if (Kind != k_VectorIndex) return false;
900 return VectorIndex.Val < 2;
901 }
902
903
904
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000905 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +0000906 // Add as immediates when possible. Null MCExpr = 0.
907 if (Expr == 0)
908 Inst.addOperand(MCOperand::CreateImm(0));
909 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000910 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
911 else
912 Inst.addOperand(MCOperand::CreateExpr(Expr));
913 }
914
Daniel Dunbar8462b302010-08-11 06:36:53 +0000915 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000916 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000917 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +0000918 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
919 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000920 }
921
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000922 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
923 assert(N == 1 && "Invalid number of operands!");
924 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
925 }
926
Jim Grosbach89df9962011-08-26 21:43:41 +0000927 void addITMaskOperands(MCInst &Inst, unsigned N) const {
928 assert(N == 1 && "Invalid number of operands!");
929 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
930 }
931
932 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
933 assert(N == 1 && "Invalid number of operands!");
934 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
935 }
936
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000937 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
938 assert(N == 1 && "Invalid number of operands!");
939 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
940 }
941
Jim Grosbachd67641b2010-12-06 18:21:12 +0000942 void addCCOutOperands(MCInst &Inst, unsigned N) const {
943 assert(N == 1 && "Invalid number of operands!");
944 Inst.addOperand(MCOperand::CreateReg(getReg()));
945 }
946
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000947 void addRegOperands(MCInst &Inst, unsigned N) const {
948 assert(N == 1 && "Invalid number of operands!");
949 Inst.addOperand(MCOperand::CreateReg(getReg()));
950 }
951
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000952 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +0000953 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000954 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
955 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
956 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000957 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000958 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000959 }
960
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000961 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +0000962 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000963 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
964 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +0000965 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000966 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +0000967 }
968
Jim Grosbach580f4a92011-07-25 22:20:28 +0000969 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +0000970 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +0000971 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
972 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +0000973 }
974
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000975 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +0000976 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +0000977 const SmallVectorImpl<unsigned> &RegList = getRegList();
978 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +0000979 I = RegList.begin(), E = RegList.end(); I != E; ++I)
980 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000981 }
982
Bill Wendling0f630752010-11-17 04:32:08 +0000983 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
984 addRegListOperands(Inst, N);
985 }
986
987 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
988 addRegListOperands(Inst, N);
989 }
990
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000991 void addRotImmOperands(MCInst &Inst, unsigned N) const {
992 assert(N == 1 && "Invalid number of operands!");
993 // Encoded as val>>3. The printer handles display as 8, 16, 24.
994 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
995 }
996
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000997 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
998 assert(N == 1 && "Invalid number of operands!");
999 // Munge the lsb/width into a bitfield mask.
1000 unsigned lsb = Bitfield.LSB;
1001 unsigned width = Bitfield.Width;
1002 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1003 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1004 (32 - (lsb + width)));
1005 Inst.addOperand(MCOperand::CreateImm(Mask));
1006 }
1007
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001008 void addImmOperands(MCInst &Inst, unsigned N) const {
1009 assert(N == 1 && "Invalid number of operands!");
1010 addExpr(Inst, getImm());
1011 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001012
Jim Grosbach9d390362011-10-03 23:38:36 +00001013 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1014 assert(N == 1 && "Invalid number of operands!");
1015 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1016 }
1017
Jim Grosbacha77295d2011-09-08 22:07:06 +00001018 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1019 assert(N == 1 && "Invalid number of operands!");
1020 // FIXME: We really want to scale the value here, but the LDRD/STRD
1021 // instruction don't encode operands that way yet.
1022 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1023 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1024 }
1025
Jim Grosbach72f39f82011-08-24 21:22:15 +00001026 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1027 assert(N == 1 && "Invalid number of operands!");
1028 // The immediate is scaled by four in the encoding and is stored
1029 // in the MCInst as such. Lop off the low two bits here.
1030 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1031 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1032 }
1033
1034 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1035 assert(N == 1 && "Invalid number of operands!");
1036 // The immediate is scaled by four in the encoding and is stored
1037 // in the MCInst as such. Lop off the low two bits here.
1038 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1039 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1040 }
1041
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001042 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1043 assert(N == 1 && "Invalid number of operands!");
1044 addExpr(Inst, getImm());
1045 }
1046
Jim Grosbach83ab0702011-07-13 22:01:08 +00001047 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1048 assert(N == 1 && "Invalid number of operands!");
1049 addExpr(Inst, getImm());
1050 }
1051
1052 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1053 assert(N == 1 && "Invalid number of operands!");
1054 addExpr(Inst, getImm());
1055 }
1056
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001057 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1058 assert(N == 1 && "Invalid number of operands!");
1059 addExpr(Inst, getImm());
1060 }
1061
Jim Grosbachf4943352011-07-25 23:09:14 +00001062 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
1064 // The constant encodes as the immediate-1, and we store in the instruction
1065 // the bits as encoded, so subtract off one here.
1066 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1067 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1068 }
1069
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001070 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1071 assert(N == 1 && "Invalid number of operands!");
1072 // The constant encodes as the immediate-1, and we store in the instruction
1073 // the bits as encoded, so subtract off one here.
1074 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1075 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1076 }
1077
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001078 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1079 assert(N == 1 && "Invalid number of operands!");
1080 addExpr(Inst, getImm());
1081 }
1082
Jim Grosbachffa32252011-07-19 19:13:28 +00001083 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1084 assert(N == 1 && "Invalid number of operands!");
1085 addExpr(Inst, getImm());
1086 }
1087
Jim Grosbached838482011-07-26 16:24:27 +00001088 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1089 assert(N == 1 && "Invalid number of operands!");
1090 addExpr(Inst, getImm());
1091 }
1092
Jim Grosbach70939ee2011-08-17 21:51:27 +00001093 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1094 assert(N == 1 && "Invalid number of operands!");
1095 // The constant encodes as the immediate, except for 32, which encodes as
1096 // zero.
1097 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1098 unsigned Imm = CE->getValue();
1099 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1100 }
1101
Jim Grosbachf6c05252011-07-21 17:23:04 +00001102 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1103 assert(N == 1 && "Invalid number of operands!");
1104 addExpr(Inst, getImm());
1105 }
1106
1107 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
1109 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1110 // the instruction as well.
1111 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1112 int Val = CE->getValue();
1113 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1114 }
1115
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001116 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!");
1118 addExpr(Inst, getImm());
1119 }
1120
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001121 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
1123 addExpr(Inst, getImm());
1124 }
1125
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001126 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1127 assert(N == 1 && "Invalid number of operands!");
1128 addExpr(Inst, getImm());
1129 }
1130
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001131 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1132 assert(N == 1 && "Invalid number of operands!");
1133 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1134 }
1135
Jim Grosbach7ce05792011-08-03 23:50:40 +00001136 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1137 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001138 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001139 }
1140
Jim Grosbach57dcb852011-10-11 17:29:55 +00001141 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1142 assert(N == 2 && "Invalid number of operands!");
1143 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1144 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1145 }
1146
Jim Grosbach7ce05792011-08-03 23:50:40 +00001147 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1148 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001149 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1150 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001151 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1152 // Special case for #-0
1153 if (Val == INT32_MIN) Val = 0;
1154 if (Val < 0) Val = -Val;
1155 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1156 } else {
1157 // For register offset, we encode the shift type and negation flag
1158 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001159 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1160 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001161 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001162 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1163 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001164 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001165 }
1166
Jim Grosbach039c2e12011-08-04 23:01:30 +00001167 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1168 assert(N == 2 && "Invalid number of operands!");
1169 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1170 assert(CE && "non-constant AM2OffsetImm operand!");
1171 int32_t Val = CE->getValue();
1172 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1173 // Special case for #-0
1174 if (Val == INT32_MIN) Val = 0;
1175 if (Val < 0) Val = -Val;
1176 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1177 Inst.addOperand(MCOperand::CreateReg(0));
1178 Inst.addOperand(MCOperand::CreateImm(Val));
1179 }
1180
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001181 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1182 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001183 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1184 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001185 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1186 // Special case for #-0
1187 if (Val == INT32_MIN) Val = 0;
1188 if (Val < 0) Val = -Val;
1189 Val = ARM_AM::getAM3Opc(AddSub, Val);
1190 } else {
1191 // For register offset, we encode the shift type and negation flag
1192 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001193 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001194 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001195 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1196 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001197 Inst.addOperand(MCOperand::CreateImm(Val));
1198 }
1199
1200 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1201 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001202 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001203 int32_t Val =
1204 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1205 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1206 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001207 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001208 }
1209
1210 // Constant offset.
1211 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1212 int32_t Val = CE->getValue();
1213 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1214 // Special case for #-0
1215 if (Val == INT32_MIN) Val = 0;
1216 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001217 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001218 Inst.addOperand(MCOperand::CreateReg(0));
1219 Inst.addOperand(MCOperand::CreateImm(Val));
1220 }
1221
Jim Grosbach7ce05792011-08-03 23:50:40 +00001222 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1223 assert(N == 2 && "Invalid number of operands!");
1224 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001225 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001226 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1227 // Special case for #-0
1228 if (Val == INT32_MIN) Val = 0;
1229 if (Val < 0) Val = -Val;
1230 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001231 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001232 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001233 }
1234
Jim Grosbacha77295d2011-09-08 22:07:06 +00001235 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1236 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001237 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1238 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001239 Inst.addOperand(MCOperand::CreateImm(Val));
1240 }
1241
Jim Grosbachb6aed502011-09-09 18:37:27 +00001242 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1243 assert(N == 2 && "Invalid number of operands!");
1244 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001245 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1246 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001247 Inst.addOperand(MCOperand::CreateImm(Val));
1248 }
1249
Jim Grosbach7ce05792011-08-03 23:50:40 +00001250 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1251 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001252 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1253 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001254 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001255 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001256
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001257 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1258 addMemImm8OffsetOperands(Inst, N);
1259 }
1260
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001261 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001262 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001263 }
1264
1265 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1266 assert(N == 2 && "Invalid number of operands!");
1267 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001268 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001269 addExpr(Inst, getImm());
1270 Inst.addOperand(MCOperand::CreateImm(0));
1271 return;
1272 }
1273
1274 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001275 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1276 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001277 Inst.addOperand(MCOperand::CreateImm(Val));
1278 }
1279
Jim Grosbach7ce05792011-08-03 23:50:40 +00001280 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001282 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001283 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001284 addExpr(Inst, getImm());
1285 Inst.addOperand(MCOperand::CreateImm(0));
1286 return;
1287 }
1288
1289 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001290 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1291 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001292 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001293 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001294
Jim Grosbach7f739be2011-09-19 22:21:13 +00001295 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001297 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1298 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001299 }
1300
1301 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1302 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001303 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1304 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001305 }
1306
Jim Grosbach7ce05792011-08-03 23:50:40 +00001307 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1308 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001309 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1310 Memory.ShiftImm, Memory.ShiftType);
1311 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1312 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001313 Inst.addOperand(MCOperand::CreateImm(Val));
1314 }
1315
Jim Grosbachab899c12011-09-07 23:10:15 +00001316 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1317 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001318 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1319 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1320 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001321 }
1322
Jim Grosbach7ce05792011-08-03 23:50:40 +00001323 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001325 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1326 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001327 }
1328
Jim Grosbach60f91a32011-08-19 17:55:24 +00001329 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1330 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001331 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1332 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001333 Inst.addOperand(MCOperand::CreateImm(Val));
1334 }
1335
Jim Grosbach38466302011-08-19 18:55:51 +00001336 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1337 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001338 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1339 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001340 Inst.addOperand(MCOperand::CreateImm(Val));
1341 }
1342
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001343 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1344 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001345 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1346 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001347 Inst.addOperand(MCOperand::CreateImm(Val));
1348 }
1349
Jim Grosbachecd85892011-08-19 18:13:48 +00001350 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1351 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001352 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1353 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001354 Inst.addOperand(MCOperand::CreateImm(Val));
1355 }
1356
Jim Grosbach7ce05792011-08-03 23:50:40 +00001357 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1358 assert(N == 1 && "Invalid number of operands!");
1359 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1360 assert(CE && "non-constant post-idx-imm8 operand!");
1361 int Imm = CE->getValue();
1362 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001363 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001364 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1365 Inst.addOperand(MCOperand::CreateImm(Imm));
1366 }
1367
Jim Grosbach2bd01182011-10-11 21:55:36 +00001368 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1371 assert(CE && "non-constant post-idx-imm8s4 operand!");
1372 int Imm = CE->getValue();
1373 bool isAdd = Imm >= 0;
1374 if (Imm == INT32_MIN) Imm = 0;
1375 // Immediate is scaled by 4.
1376 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1377 Inst.addOperand(MCOperand::CreateImm(Imm));
1378 }
1379
Jim Grosbach7ce05792011-08-03 23:50:40 +00001380 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1381 assert(N == 2 && "Invalid number of operands!");
1382 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001383 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1384 }
1385
1386 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1387 assert(N == 2 && "Invalid number of operands!");
1388 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1389 // The sign, shift type, and shift amount are encoded in a single operand
1390 // using the AM2 encoding helpers.
1391 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1392 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1393 PostIdxReg.ShiftTy);
1394 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001395 }
1396
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001397 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1398 assert(N == 1 && "Invalid number of operands!");
1399 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1400 }
1401
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001402 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 1 && "Invalid number of operands!");
1404 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1405 }
1406
Jim Grosbach460a9052011-10-07 23:56:00 +00001407 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1408 assert(N == 1 && "Invalid number of operands!");
1409 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1410 }
1411
1412 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1413 assert(N == 1 && "Invalid number of operands!");
1414 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1415 }
1416
1417 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1418 assert(N == 1 && "Invalid number of operands!");
1419 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1420 }
1421
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001422 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001423
Jim Grosbach89df9962011-08-26 21:43:41 +00001424 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001425 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001426 Op->ITMask.Mask = Mask;
1427 Op->StartLoc = S;
1428 Op->EndLoc = S;
1429 return Op;
1430 }
1431
Chris Lattner3a697562010-10-28 17:20:03 +00001432 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001433 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001434 Op->CC.Val = CC;
1435 Op->StartLoc = S;
1436 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001437 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001438 }
1439
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001440 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001441 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001442 Op->Cop.Val = CopVal;
1443 Op->StartLoc = S;
1444 Op->EndLoc = S;
1445 return Op;
1446 }
1447
1448 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001449 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001450 Op->Cop.Val = CopVal;
1451 Op->StartLoc = S;
1452 Op->EndLoc = S;
1453 return Op;
1454 }
1455
Jim Grosbachd67641b2010-12-06 18:21:12 +00001456 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001457 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001458 Op->Reg.RegNum = RegNum;
1459 Op->StartLoc = S;
1460 Op->EndLoc = S;
1461 return Op;
1462 }
1463
Chris Lattner3a697562010-10-28 17:20:03 +00001464 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001465 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001466 Op->Tok.Data = Str.data();
1467 Op->Tok.Length = Str.size();
1468 Op->StartLoc = S;
1469 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001470 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001471 }
1472
Bill Wendling50d0f582010-11-18 23:43:05 +00001473 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001474 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001475 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001476 Op->StartLoc = S;
1477 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001478 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001479 }
1480
Jim Grosbache8606dc2011-07-13 17:50:29 +00001481 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1482 unsigned SrcReg,
1483 unsigned ShiftReg,
1484 unsigned ShiftImm,
1485 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001486 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001487 Op->RegShiftedReg.ShiftTy = ShTy;
1488 Op->RegShiftedReg.SrcReg = SrcReg;
1489 Op->RegShiftedReg.ShiftReg = ShiftReg;
1490 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001491 Op->StartLoc = S;
1492 Op->EndLoc = E;
1493 return Op;
1494 }
1495
Owen Anderson92a20222011-07-21 18:54:16 +00001496 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1497 unsigned SrcReg,
1498 unsigned ShiftImm,
1499 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001500 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001501 Op->RegShiftedImm.ShiftTy = ShTy;
1502 Op->RegShiftedImm.SrcReg = SrcReg;
1503 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001504 Op->StartLoc = S;
1505 Op->EndLoc = E;
1506 return Op;
1507 }
1508
Jim Grosbach580f4a92011-07-25 22:20:28 +00001509 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001510 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001511 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001512 Op->ShifterImm.isASR = isASR;
1513 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001514 Op->StartLoc = S;
1515 Op->EndLoc = E;
1516 return Op;
1517 }
1518
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001519 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001520 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001521 Op->RotImm.Imm = Imm;
1522 Op->StartLoc = S;
1523 Op->EndLoc = E;
1524 return Op;
1525 }
1526
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001527 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1528 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001529 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001530 Op->Bitfield.LSB = LSB;
1531 Op->Bitfield.Width = Width;
1532 Op->StartLoc = S;
1533 Op->EndLoc = E;
1534 return Op;
1535 }
1536
Bill Wendling7729e062010-11-09 22:44:22 +00001537 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001538 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001539 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001540 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001541
Jim Grosbachd300b942011-09-13 22:56:44 +00001542 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001543 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001544 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001545 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001546 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001547
1548 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001549 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001550 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001551 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001552 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001553 Op->StartLoc = StartLoc;
1554 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001555 return Op;
1556 }
1557
Jim Grosbach460a9052011-10-07 23:56:00 +00001558 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1559 MCContext &Ctx) {
1560 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1561 Op->VectorIndex.Val = Idx;
1562 Op->StartLoc = S;
1563 Op->EndLoc = E;
1564 return Op;
1565 }
1566
Chris Lattner3a697562010-10-28 17:20:03 +00001567 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001568 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001569 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001570 Op->StartLoc = S;
1571 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001572 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001573 }
1574
Jim Grosbach9d390362011-10-03 23:38:36 +00001575 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001576 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001577 Op->FPImm.Val = Val;
1578 Op->StartLoc = S;
1579 Op->EndLoc = S;
1580 return Op;
1581 }
1582
Jim Grosbach7ce05792011-08-03 23:50:40 +00001583 static ARMOperand *CreateMem(unsigned BaseRegNum,
1584 const MCConstantExpr *OffsetImm,
1585 unsigned OffsetRegNum,
1586 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001587 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001588 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001589 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001590 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001591 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001592 Op->Memory.BaseRegNum = BaseRegNum;
1593 Op->Memory.OffsetImm = OffsetImm;
1594 Op->Memory.OffsetRegNum = OffsetRegNum;
1595 Op->Memory.ShiftType = ShiftType;
1596 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001597 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001598 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001599 Op->StartLoc = S;
1600 Op->EndLoc = E;
1601 return Op;
1602 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001603
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001604 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1605 ARM_AM::ShiftOpc ShiftTy,
1606 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001607 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001608 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001609 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001610 Op->PostIdxReg.isAdd = isAdd;
1611 Op->PostIdxReg.ShiftTy = ShiftTy;
1612 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001613 Op->StartLoc = S;
1614 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001615 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001616 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001617
1618 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001619 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001620 Op->MBOpt.Val = Opt;
1621 Op->StartLoc = S;
1622 Op->EndLoc = S;
1623 return Op;
1624 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001625
1626 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001627 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001628 Op->IFlags.Val = IFlags;
1629 Op->StartLoc = S;
1630 Op->EndLoc = S;
1631 return Op;
1632 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001633
1634 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001635 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001636 Op->MMask.Val = MMask;
1637 Op->StartLoc = S;
1638 Op->EndLoc = S;
1639 return Op;
1640 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001641};
1642
1643} // end anonymous namespace.
1644
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001645void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001646 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001647 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001648 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1649 << ") >";
1650 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001651 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001652 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001653 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001654 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001655 OS << "<ccout " << getReg() << ">";
1656 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001657 case k_ITCondMask: {
Jim Grosbach89df9962011-08-26 21:43:41 +00001658 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1659 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1660 "(tee)", "(eee)" };
1661 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1662 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1663 break;
1664 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001665 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001666 OS << "<coprocessor number: " << getCoproc() << ">";
1667 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001668 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001669 OS << "<coprocessor register: " << getCoproc() << ">";
1670 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001671 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001672 OS << "<mask: " << getMSRMask() << ">";
1673 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001674 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001675 getImm()->print(OS);
1676 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001677 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001678 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1679 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001680 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001681 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001682 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001683 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001684 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001685 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001686 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1687 << PostIdxReg.RegNum;
1688 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1689 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1690 << PostIdxReg.ShiftImm;
1691 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001692 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001693 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001694 OS << "<ARM_PROC::";
1695 unsigned IFlags = getProcIFlags();
1696 for (int i=2; i >= 0; --i)
1697 if (IFlags & (1 << i))
1698 OS << ARM_PROC::IFlagsToString(1 << i);
1699 OS << ">";
1700 break;
1701 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001702 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001703 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001704 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001705 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001706 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1707 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001708 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001709 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001710 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001711 << RegShiftedReg.SrcReg
1712 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1713 << ", " << RegShiftedReg.ShiftReg << ", "
1714 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001715 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001716 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001717 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001718 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001719 << RegShiftedImm.SrcReg
1720 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1721 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001722 << ">";
1723 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001724 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001725 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1726 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001727 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001728 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1729 << ", width: " << Bitfield.Width << ">";
1730 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001731 case k_RegisterList:
1732 case k_DPRRegisterList:
1733 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001734 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001735
Bill Wendling5fa22a12010-11-09 23:28:44 +00001736 const SmallVectorImpl<unsigned> &RegList = getRegList();
1737 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001738 I = RegList.begin(), E = RegList.end(); I != E; ) {
1739 OS << *I;
1740 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001741 }
1742
1743 OS << ">";
1744 break;
1745 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001746 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001747 OS << "'" << getToken() << "'";
1748 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001749 case k_VectorIndex:
1750 OS << "<vectorindex " << getVectorIndex() << ">";
1751 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001752 }
1753}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001754
1755/// @name Auto-generated Match Functions
1756/// {
1757
1758static unsigned MatchRegisterName(StringRef Name);
1759
1760/// }
1761
Bob Wilson69df7232011-02-03 21:46:10 +00001762bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1763 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001764 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001765
1766 return (RegNo == (unsigned)-1);
1767}
1768
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001769/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001770/// and if it is a register name the token is eaten and the register number is
1771/// returned. Otherwise return -1.
1772///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001773int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001774 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001775 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001776
Chris Lattnere5658fa2010-10-30 04:09:10 +00001777 // FIXME: Validate register for the current architecture; we have to do
1778 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00001779 std::string upperCase = Tok.getString().str();
1780 std::string lowerCase = LowercaseString(upperCase);
1781 unsigned RegNum = MatchRegisterName(lowerCase);
1782 if (!RegNum) {
1783 RegNum = StringSwitch<unsigned>(lowerCase)
1784 .Case("r13", ARM::SP)
1785 .Case("r14", ARM::LR)
1786 .Case("r15", ARM::PC)
1787 .Case("ip", ARM::R12)
1788 .Default(0);
1789 }
1790 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00001791
Chris Lattnere5658fa2010-10-30 04:09:10 +00001792 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00001793
1794#if 0
1795 // Also check for an index operand. This is only legal for vector registers,
1796 // but that'll get caught OK in operand matching, so we don't need to
1797 // explicitly filter everything else out here.
1798 if (Parser.getTok().is(AsmToken::LBrac)) {
1799 SMLoc SIdx = Parser.getTok().getLoc();
1800 Parser.Lex(); // Eat left bracket token.
1801
1802 const MCExpr *ImmVal;
1803 SMLoc ExprLoc = Parser.getTok().getLoc();
1804 if (getParser().ParseExpression(ImmVal))
1805 return MatchOperand_ParseFail;
1806 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1807 if (!MCE) {
1808 TokError("immediate value expected for vector index");
1809 return MatchOperand_ParseFail;
1810 }
1811
1812 SMLoc E = Parser.getTok().getLoc();
1813 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1814 Error(E, "']' expected");
1815 return MatchOperand_ParseFail;
1816 }
1817
1818 Parser.Lex(); // Eat right bracket token.
1819
1820 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1821 SIdx, E,
1822 getContext()));
1823 }
1824#endif
1825
Chris Lattnere5658fa2010-10-30 04:09:10 +00001826 return RegNum;
1827}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001828
Jim Grosbach19906722011-07-13 18:49:30 +00001829// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1830// If a recoverable error occurs, return 1. If an irrecoverable error
1831// occurs, return -1. An irrecoverable error is one where tokens have been
1832// consumed in the process of trying to parse the shifter (i.e., when it is
1833// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00001834int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00001835 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1836 SMLoc S = Parser.getTok().getLoc();
1837 const AsmToken &Tok = Parser.getTok();
1838 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1839
1840 std::string upperCase = Tok.getString().str();
1841 std::string lowerCase = LowercaseString(upperCase);
1842 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1843 .Case("lsl", ARM_AM::lsl)
1844 .Case("lsr", ARM_AM::lsr)
1845 .Case("asr", ARM_AM::asr)
1846 .Case("ror", ARM_AM::ror)
1847 .Case("rrx", ARM_AM::rrx)
1848 .Default(ARM_AM::no_shift);
1849
1850 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00001851 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00001852
Jim Grosbache8606dc2011-07-13 17:50:29 +00001853 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00001854
Jim Grosbache8606dc2011-07-13 17:50:29 +00001855 // The source register for the shift has already been added to the
1856 // operand list, so we need to pop it off and combine it into the shifted
1857 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00001858 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00001859 if (!PrevOp->isReg())
1860 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1861 int SrcReg = PrevOp->getReg();
1862 int64_t Imm = 0;
1863 int ShiftReg = 0;
1864 if (ShiftTy == ARM_AM::rrx) {
1865 // RRX Doesn't have an explicit shift amount. The encoder expects
1866 // the shift register to be the same as the source register. Seems odd,
1867 // but OK.
1868 ShiftReg = SrcReg;
1869 } else {
1870 // Figure out if this is shifted by a constant or a register (for non-RRX).
1871 if (Parser.getTok().is(AsmToken::Hash)) {
1872 Parser.Lex(); // Eat hash.
1873 SMLoc ImmLoc = Parser.getTok().getLoc();
1874 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00001875 if (getParser().ParseExpression(ShiftExpr)) {
1876 Error(ImmLoc, "invalid immediate shift value");
1877 return -1;
1878 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001879 // The expression must be evaluatable as an immediate.
1880 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00001881 if (!CE) {
1882 Error(ImmLoc, "invalid immediate shift value");
1883 return -1;
1884 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001885 // Range check the immediate.
1886 // lsl, ror: 0 <= imm <= 31
1887 // lsr, asr: 0 <= imm <= 32
1888 Imm = CE->getValue();
1889 if (Imm < 0 ||
1890 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
1891 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00001892 Error(ImmLoc, "immediate shift value out of range");
1893 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001894 }
1895 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001896 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00001897 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00001898 if (ShiftReg == -1) {
1899 Error (L, "expected immediate or register in shift operand");
1900 return -1;
1901 }
1902 } else {
1903 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00001904 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00001905 return -1;
1906 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001907 }
1908
Owen Anderson92a20222011-07-21 18:54:16 +00001909 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1910 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001911 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001912 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00001913 else
1914 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1915 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00001916
Jim Grosbach19906722011-07-13 18:49:30 +00001917 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00001918}
1919
1920
Bill Wendling50d0f582010-11-18 23:43:05 +00001921/// Try to parse a register name. The token must be an Identifier when called.
1922/// If it's a register, an AsmOperand is created. Another AsmOperand is created
1923/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00001924///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001925/// TODO this is likely to change to allow different register types and or to
1926/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00001927bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001928tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001929 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00001930 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00001931 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00001932 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001933
Bill Wendling50d0f582010-11-18 23:43:05 +00001934 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001935
Chris Lattnere5658fa2010-10-30 04:09:10 +00001936 const AsmToken &ExclaimTok = Parser.getTok();
1937 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00001938 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
1939 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00001940 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00001941 return false;
1942 }
1943
1944 // Also check for an index operand. This is only legal for vector registers,
1945 // but that'll get caught OK in operand matching, so we don't need to
1946 // explicitly filter everything else out here.
1947 if (Parser.getTok().is(AsmToken::LBrac)) {
1948 SMLoc SIdx = Parser.getTok().getLoc();
1949 Parser.Lex(); // Eat left bracket token.
1950
1951 const MCExpr *ImmVal;
1952 SMLoc ExprLoc = Parser.getTok().getLoc();
1953 if (getParser().ParseExpression(ImmVal))
1954 return MatchOperand_ParseFail;
1955 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1956 if (!MCE) {
1957 TokError("immediate value expected for vector index");
1958 return MatchOperand_ParseFail;
1959 }
1960
1961 SMLoc E = Parser.getTok().getLoc();
1962 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1963 Error(E, "']' expected");
1964 return MatchOperand_ParseFail;
1965 }
1966
1967 Parser.Lex(); // Eat right bracket token.
1968
1969 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1970 SIdx, E,
1971 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00001972 }
1973
Bill Wendling50d0f582010-11-18 23:43:05 +00001974 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001975}
1976
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001977/// MatchCoprocessorOperandName - Try to parse an coprocessor related
1978/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
1979/// "c5", ...
1980static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001981 // Use the same layout as the tablegen'erated register name matcher. Ugly,
1982 // but efficient.
1983 switch (Name.size()) {
1984 default: break;
1985 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001986 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001987 return -1;
1988 switch (Name[1]) {
1989 default: return -1;
1990 case '0': return 0;
1991 case '1': return 1;
1992 case '2': return 2;
1993 case '3': return 3;
1994 case '4': return 4;
1995 case '5': return 5;
1996 case '6': return 6;
1997 case '7': return 7;
1998 case '8': return 8;
1999 case '9': return 9;
2000 }
2001 break;
2002 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002003 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002004 return -1;
2005 switch (Name[2]) {
2006 default: return -1;
2007 case '0': return 10;
2008 case '1': return 11;
2009 case '2': return 12;
2010 case '3': return 13;
2011 case '4': return 14;
2012 case '5': return 15;
2013 }
2014 break;
2015 }
2016
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002017 return -1;
2018}
2019
Jim Grosbach89df9962011-08-26 21:43:41 +00002020/// parseITCondCode - Try to parse a condition code for an IT instruction.
2021ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2022parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2023 SMLoc S = Parser.getTok().getLoc();
2024 const AsmToken &Tok = Parser.getTok();
2025 if (!Tok.is(AsmToken::Identifier))
2026 return MatchOperand_NoMatch;
2027 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2028 .Case("eq", ARMCC::EQ)
2029 .Case("ne", ARMCC::NE)
2030 .Case("hs", ARMCC::HS)
2031 .Case("cs", ARMCC::HS)
2032 .Case("lo", ARMCC::LO)
2033 .Case("cc", ARMCC::LO)
2034 .Case("mi", ARMCC::MI)
2035 .Case("pl", ARMCC::PL)
2036 .Case("vs", ARMCC::VS)
2037 .Case("vc", ARMCC::VC)
2038 .Case("hi", ARMCC::HI)
2039 .Case("ls", ARMCC::LS)
2040 .Case("ge", ARMCC::GE)
2041 .Case("lt", ARMCC::LT)
2042 .Case("gt", ARMCC::GT)
2043 .Case("le", ARMCC::LE)
2044 .Case("al", ARMCC::AL)
2045 .Default(~0U);
2046 if (CC == ~0U)
2047 return MatchOperand_NoMatch;
2048 Parser.Lex(); // Eat the token.
2049
2050 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2051
2052 return MatchOperand_Success;
2053}
2054
Jim Grosbach43904292011-07-25 20:14:50 +00002055/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002056/// token must be an Identifier when called, and if it is a coprocessor
2057/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002058ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002059parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002060 SMLoc S = Parser.getTok().getLoc();
2061 const AsmToken &Tok = Parser.getTok();
2062 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2063
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002064 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002065 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002066 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002067
2068 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002069 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002070 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002071}
2072
Jim Grosbach43904292011-07-25 20:14:50 +00002073/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002074/// token must be an Identifier when called, and if it is a coprocessor
2075/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002076ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002077parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002078 SMLoc S = Parser.getTok().getLoc();
2079 const AsmToken &Tok = Parser.getTok();
2080 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2081
2082 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2083 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002084 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002085
2086 Parser.Lex(); // Eat identifier token.
2087 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002088 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002089}
2090
Jim Grosbachd0588e22011-09-14 18:08:35 +00002091// For register list parsing, we need to map from raw GPR register numbering
2092// to the enumeration values. The enumeration values aren't sorted by
2093// register number due to our using "sp", "lr" and "pc" as canonical names.
2094static unsigned getNextRegister(unsigned Reg) {
2095 // If this is a GPR, we need to do it manually, otherwise we can rely
2096 // on the sort ordering of the enumeration since the other reg-classes
2097 // are sane.
2098 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2099 return Reg + 1;
2100 switch(Reg) {
2101 default: assert(0 && "Invalid GPR number!");
2102 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2103 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2104 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2105 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2106 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2107 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2108 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2109 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2110 }
2111}
2112
2113/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002114bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002115parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002116 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002117 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002118 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002119 Parser.Lex(); // Eat '{' token.
2120 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002121
Jim Grosbachd0588e22011-09-14 18:08:35 +00002122 // Check the first register in the list to see what register class
2123 // this is a list of.
2124 int Reg = tryParseRegister();
2125 if (Reg == -1)
2126 return Error(RegLoc, "register expected");
2127
2128 MCRegisterClass *RC;
2129 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2130 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2131 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2132 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2133 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2134 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2135 else
2136 return Error(RegLoc, "invalid register in register list");
2137
2138 // The reglist instructions have at most 16 registers, so reserve
2139 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002140 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002141 // Store the first register.
2142 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002143
Jim Grosbachd0588e22011-09-14 18:08:35 +00002144 // This starts immediately after the first register token in the list,
2145 // so we can see either a comma or a minus (range separator) as a legal
2146 // next token.
2147 while (Parser.getTok().is(AsmToken::Comma) ||
2148 Parser.getTok().is(AsmToken::Minus)) {
2149 if (Parser.getTok().is(AsmToken::Minus)) {
2150 Parser.Lex(); // Eat the comma.
2151 SMLoc EndLoc = Parser.getTok().getLoc();
2152 int EndReg = tryParseRegister();
2153 if (EndReg == -1)
2154 return Error(EndLoc, "register expected");
2155 // If the register is the same as the start reg, there's nothing
2156 // more to do.
2157 if (Reg == EndReg)
2158 continue;
2159 // The register must be in the same register class as the first.
2160 if (!RC->contains(EndReg))
2161 return Error(EndLoc, "invalid register in register list");
2162 // Ranges must go from low to high.
2163 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2164 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002165
Jim Grosbachd0588e22011-09-14 18:08:35 +00002166 // Add all the registers in the range to the register list.
2167 while (Reg != EndReg) {
2168 Reg = getNextRegister(Reg);
2169 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2170 }
2171 continue;
2172 }
2173 Parser.Lex(); // Eat the comma.
2174 RegLoc = Parser.getTok().getLoc();
2175 int OldReg = Reg;
2176 Reg = tryParseRegister();
2177 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002178 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002179 // The register must be in the same register class as the first.
2180 if (!RC->contains(Reg))
2181 return Error(RegLoc, "invalid register in register list");
2182 // List must be monotonically increasing.
2183 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2184 return Error(RegLoc, "register list not in ascending order");
2185 // VFP register lists must also be contiguous.
2186 // It's OK to use the enumeration values directly here rather, as the
2187 // VFP register classes have the enum sorted properly.
2188 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2189 Reg != OldReg + 1)
2190 return Error(RegLoc, "non-contiguous register range");
2191 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002192 }
2193
Jim Grosbachd0588e22011-09-14 18:08:35 +00002194 SMLoc E = Parser.getTok().getLoc();
2195 if (Parser.getTok().isNot(AsmToken::RCurly))
2196 return Error(E, "'}' expected");
2197 Parser.Lex(); // Eat '}' token.
2198
Bill Wendling50d0f582010-11-18 23:43:05 +00002199 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2200 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002201}
2202
Jim Grosbach43904292011-07-25 20:14:50 +00002203/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002204ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002205parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002206 SMLoc S = Parser.getTok().getLoc();
2207 const AsmToken &Tok = Parser.getTok();
2208 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2209 StringRef OptStr = Tok.getString();
2210
2211 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2212 .Case("sy", ARM_MB::SY)
2213 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002214 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002215 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002216 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002217 .Case("ishst", ARM_MB::ISHST)
2218 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002219 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002220 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002221 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002222 .Case("osh", ARM_MB::OSH)
2223 .Case("oshst", ARM_MB::OSHST)
2224 .Default(~0U);
2225
2226 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002227 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002228
2229 Parser.Lex(); // Eat identifier token.
2230 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002231 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002232}
2233
Jim Grosbach43904292011-07-25 20:14:50 +00002234/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002235ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002236parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002237 SMLoc S = Parser.getTok().getLoc();
2238 const AsmToken &Tok = Parser.getTok();
2239 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2240 StringRef IFlagsStr = Tok.getString();
2241
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002242 // An iflags string of "none" is interpreted to mean that none of the AIF
2243 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002244 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002245 if (IFlagsStr != "none") {
2246 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2247 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2248 .Case("a", ARM_PROC::A)
2249 .Case("i", ARM_PROC::I)
2250 .Case("f", ARM_PROC::F)
2251 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002252
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002253 // If some specific iflag is already set, it means that some letter is
2254 // present more than once, this is not acceptable.
2255 if (Flag == ~0U || (IFlags & Flag))
2256 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002257
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002258 IFlags |= Flag;
2259 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002260 }
2261
2262 Parser.Lex(); // Eat identifier token.
2263 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2264 return MatchOperand_Success;
2265}
2266
Jim Grosbach43904292011-07-25 20:14:50 +00002267/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002268ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002269parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002270 SMLoc S = Parser.getTok().getLoc();
2271 const AsmToken &Tok = Parser.getTok();
2272 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2273 StringRef Mask = Tok.getString();
2274
James Molloyacad68d2011-09-28 14:21:38 +00002275 if (isMClass()) {
2276 // See ARMv6-M 10.1.1
2277 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2278 .Case("apsr", 0)
2279 .Case("iapsr", 1)
2280 .Case("eapsr", 2)
2281 .Case("xpsr", 3)
2282 .Case("ipsr", 5)
2283 .Case("epsr", 6)
2284 .Case("iepsr", 7)
2285 .Case("msp", 8)
2286 .Case("psp", 9)
2287 .Case("primask", 16)
2288 .Case("basepri", 17)
2289 .Case("basepri_max", 18)
2290 .Case("faultmask", 19)
2291 .Case("control", 20)
2292 .Default(~0U);
2293
2294 if (FlagsVal == ~0U)
2295 return MatchOperand_NoMatch;
2296
2297 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2298 // basepri, basepri_max and faultmask only valid for V7m.
2299 return MatchOperand_NoMatch;
2300
2301 Parser.Lex(); // Eat identifier token.
2302 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2303 return MatchOperand_Success;
2304 }
2305
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002306 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2307 size_t Start = 0, Next = Mask.find('_');
2308 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002309 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002310 if (Next != StringRef::npos)
2311 Flags = Mask.slice(Next+1, Mask.size());
2312
2313 // FlagsVal contains the complete mask:
2314 // 3-0: Mask
2315 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2316 unsigned FlagsVal = 0;
2317
2318 if (SpecReg == "apsr") {
2319 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002320 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002321 .Case("g", 0x4) // same as CPSR_s
2322 .Case("nzcvqg", 0xc) // same as CPSR_fs
2323 .Default(~0U);
2324
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002325 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002326 if (!Flags.empty())
2327 return MatchOperand_NoMatch;
2328 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002329 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002330 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002331 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002332 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2333 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002334 for (int i = 0, e = Flags.size(); i != e; ++i) {
2335 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2336 .Case("c", 1)
2337 .Case("x", 2)
2338 .Case("s", 4)
2339 .Case("f", 8)
2340 .Default(~0U);
2341
2342 // If some specific flag is already set, it means that some letter is
2343 // present more than once, this is not acceptable.
2344 if (FlagsVal == ~0U || (FlagsVal & Flag))
2345 return MatchOperand_NoMatch;
2346 FlagsVal |= Flag;
2347 }
2348 } else // No match for special register.
2349 return MatchOperand_NoMatch;
2350
2351 // Special register without flags are equivalent to "fc" flags.
2352 if (!FlagsVal)
2353 FlagsVal = 0x9;
2354
2355 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2356 if (SpecReg == "spsr")
2357 FlagsVal |= 16;
2358
2359 Parser.Lex(); // Eat identifier token.
2360 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2361 return MatchOperand_Success;
2362}
2363
Jim Grosbachf6c05252011-07-21 17:23:04 +00002364ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2365parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2366 int Low, int High) {
2367 const AsmToken &Tok = Parser.getTok();
2368 if (Tok.isNot(AsmToken::Identifier)) {
2369 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2370 return MatchOperand_ParseFail;
2371 }
2372 StringRef ShiftName = Tok.getString();
2373 std::string LowerOp = LowercaseString(Op);
2374 std::string UpperOp = UppercaseString(Op);
2375 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2376 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2377 return MatchOperand_ParseFail;
2378 }
2379 Parser.Lex(); // Eat shift type token.
2380
2381 // There must be a '#' and a shift amount.
2382 if (Parser.getTok().isNot(AsmToken::Hash)) {
2383 Error(Parser.getTok().getLoc(), "'#' expected");
2384 return MatchOperand_ParseFail;
2385 }
2386 Parser.Lex(); // Eat hash token.
2387
2388 const MCExpr *ShiftAmount;
2389 SMLoc Loc = Parser.getTok().getLoc();
2390 if (getParser().ParseExpression(ShiftAmount)) {
2391 Error(Loc, "illegal expression");
2392 return MatchOperand_ParseFail;
2393 }
2394 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2395 if (!CE) {
2396 Error(Loc, "constant expression expected");
2397 return MatchOperand_ParseFail;
2398 }
2399 int Val = CE->getValue();
2400 if (Val < Low || Val > High) {
2401 Error(Loc, "immediate value out of range");
2402 return MatchOperand_ParseFail;
2403 }
2404
2405 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2406
2407 return MatchOperand_Success;
2408}
2409
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002410ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2411parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2412 const AsmToken &Tok = Parser.getTok();
2413 SMLoc S = Tok.getLoc();
2414 if (Tok.isNot(AsmToken::Identifier)) {
2415 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2416 return MatchOperand_ParseFail;
2417 }
2418 int Val = StringSwitch<int>(Tok.getString())
2419 .Case("be", 1)
2420 .Case("le", 0)
2421 .Default(-1);
2422 Parser.Lex(); // Eat the token.
2423
2424 if (Val == -1) {
2425 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2426 return MatchOperand_ParseFail;
2427 }
2428 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2429 getContext()),
2430 S, Parser.getTok().getLoc()));
2431 return MatchOperand_Success;
2432}
2433
Jim Grosbach580f4a92011-07-25 22:20:28 +00002434/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2435/// instructions. Legal values are:
2436/// lsl #n 'n' in [0,31]
2437/// asr #n 'n' in [1,32]
2438/// n == 32 encoded as n == 0.
2439ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2440parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2441 const AsmToken &Tok = Parser.getTok();
2442 SMLoc S = Tok.getLoc();
2443 if (Tok.isNot(AsmToken::Identifier)) {
2444 Error(S, "shift operator 'asr' or 'lsl' expected");
2445 return MatchOperand_ParseFail;
2446 }
2447 StringRef ShiftName = Tok.getString();
2448 bool isASR;
2449 if (ShiftName == "lsl" || ShiftName == "LSL")
2450 isASR = false;
2451 else if (ShiftName == "asr" || ShiftName == "ASR")
2452 isASR = true;
2453 else {
2454 Error(S, "shift operator 'asr' or 'lsl' expected");
2455 return MatchOperand_ParseFail;
2456 }
2457 Parser.Lex(); // Eat the operator.
2458
2459 // A '#' and a shift amount.
2460 if (Parser.getTok().isNot(AsmToken::Hash)) {
2461 Error(Parser.getTok().getLoc(), "'#' expected");
2462 return MatchOperand_ParseFail;
2463 }
2464 Parser.Lex(); // Eat hash token.
2465
2466 const MCExpr *ShiftAmount;
2467 SMLoc E = Parser.getTok().getLoc();
2468 if (getParser().ParseExpression(ShiftAmount)) {
2469 Error(E, "malformed shift expression");
2470 return MatchOperand_ParseFail;
2471 }
2472 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2473 if (!CE) {
2474 Error(E, "shift amount must be an immediate");
2475 return MatchOperand_ParseFail;
2476 }
2477
2478 int64_t Val = CE->getValue();
2479 if (isASR) {
2480 // Shift amount must be in [1,32]
2481 if (Val < 1 || Val > 32) {
2482 Error(E, "'asr' shift amount must be in range [1,32]");
2483 return MatchOperand_ParseFail;
2484 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002485 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2486 if (isThumb() && Val == 32) {
2487 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2488 return MatchOperand_ParseFail;
2489 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002490 if (Val == 32) Val = 0;
2491 } else {
2492 // Shift amount must be in [1,32]
2493 if (Val < 0 || Val > 31) {
2494 Error(E, "'lsr' shift amount must be in range [0,31]");
2495 return MatchOperand_ParseFail;
2496 }
2497 }
2498
2499 E = Parser.getTok().getLoc();
2500 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2501
2502 return MatchOperand_Success;
2503}
2504
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002505/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2506/// of instructions. Legal values are:
2507/// ror #n 'n' in {0, 8, 16, 24}
2508ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2509parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2510 const AsmToken &Tok = Parser.getTok();
2511 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002512 if (Tok.isNot(AsmToken::Identifier))
2513 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002514 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002515 if (ShiftName != "ror" && ShiftName != "ROR")
2516 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002517 Parser.Lex(); // Eat the operator.
2518
2519 // A '#' and a rotate amount.
2520 if (Parser.getTok().isNot(AsmToken::Hash)) {
2521 Error(Parser.getTok().getLoc(), "'#' expected");
2522 return MatchOperand_ParseFail;
2523 }
2524 Parser.Lex(); // Eat hash token.
2525
2526 const MCExpr *ShiftAmount;
2527 SMLoc E = Parser.getTok().getLoc();
2528 if (getParser().ParseExpression(ShiftAmount)) {
2529 Error(E, "malformed rotate expression");
2530 return MatchOperand_ParseFail;
2531 }
2532 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2533 if (!CE) {
2534 Error(E, "rotate amount must be an immediate");
2535 return MatchOperand_ParseFail;
2536 }
2537
2538 int64_t Val = CE->getValue();
2539 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2540 // normally, zero is represented in asm by omitting the rotate operand
2541 // entirely.
2542 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2543 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2544 return MatchOperand_ParseFail;
2545 }
2546
2547 E = Parser.getTok().getLoc();
2548 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2549
2550 return MatchOperand_Success;
2551}
2552
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002553ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2554parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2555 SMLoc S = Parser.getTok().getLoc();
2556 // The bitfield descriptor is really two operands, the LSB and the width.
2557 if (Parser.getTok().isNot(AsmToken::Hash)) {
2558 Error(Parser.getTok().getLoc(), "'#' expected");
2559 return MatchOperand_ParseFail;
2560 }
2561 Parser.Lex(); // Eat hash token.
2562
2563 const MCExpr *LSBExpr;
2564 SMLoc E = Parser.getTok().getLoc();
2565 if (getParser().ParseExpression(LSBExpr)) {
2566 Error(E, "malformed immediate expression");
2567 return MatchOperand_ParseFail;
2568 }
2569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2570 if (!CE) {
2571 Error(E, "'lsb' operand must be an immediate");
2572 return MatchOperand_ParseFail;
2573 }
2574
2575 int64_t LSB = CE->getValue();
2576 // The LSB must be in the range [0,31]
2577 if (LSB < 0 || LSB > 31) {
2578 Error(E, "'lsb' operand must be in the range [0,31]");
2579 return MatchOperand_ParseFail;
2580 }
2581 E = Parser.getTok().getLoc();
2582
2583 // Expect another immediate operand.
2584 if (Parser.getTok().isNot(AsmToken::Comma)) {
2585 Error(Parser.getTok().getLoc(), "too few operands");
2586 return MatchOperand_ParseFail;
2587 }
2588 Parser.Lex(); // Eat hash token.
2589 if (Parser.getTok().isNot(AsmToken::Hash)) {
2590 Error(Parser.getTok().getLoc(), "'#' expected");
2591 return MatchOperand_ParseFail;
2592 }
2593 Parser.Lex(); // Eat hash token.
2594
2595 const MCExpr *WidthExpr;
2596 if (getParser().ParseExpression(WidthExpr)) {
2597 Error(E, "malformed immediate expression");
2598 return MatchOperand_ParseFail;
2599 }
2600 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2601 if (!CE) {
2602 Error(E, "'width' operand must be an immediate");
2603 return MatchOperand_ParseFail;
2604 }
2605
2606 int64_t Width = CE->getValue();
2607 // The LSB must be in the range [1,32-lsb]
2608 if (Width < 1 || Width > 32 - LSB) {
2609 Error(E, "'width' operand must be in the range [1,32-lsb]");
2610 return MatchOperand_ParseFail;
2611 }
2612 E = Parser.getTok().getLoc();
2613
2614 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2615
2616 return MatchOperand_Success;
2617}
2618
Jim Grosbach7ce05792011-08-03 23:50:40 +00002619ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2620parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2621 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002622 // postidx_reg := '+' register {, shift}
2623 // | '-' register {, shift}
2624 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002625
2626 // This method must return MatchOperand_NoMatch without consuming any tokens
2627 // in the case where there is no match, as other alternatives take other
2628 // parse methods.
2629 AsmToken Tok = Parser.getTok();
2630 SMLoc S = Tok.getLoc();
2631 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002632 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002633 int Reg = -1;
2634 if (Tok.is(AsmToken::Plus)) {
2635 Parser.Lex(); // Eat the '+' token.
2636 haveEaten = true;
2637 } else if (Tok.is(AsmToken::Minus)) {
2638 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002639 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002640 haveEaten = true;
2641 }
2642 if (Parser.getTok().is(AsmToken::Identifier))
2643 Reg = tryParseRegister();
2644 if (Reg == -1) {
2645 if (!haveEaten)
2646 return MatchOperand_NoMatch;
2647 Error(Parser.getTok().getLoc(), "register expected");
2648 return MatchOperand_ParseFail;
2649 }
2650 SMLoc E = Parser.getTok().getLoc();
2651
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002652 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2653 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002654 if (Parser.getTok().is(AsmToken::Comma)) {
2655 Parser.Lex(); // Eat the ','.
2656 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2657 return MatchOperand_ParseFail;
2658 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002659
2660 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2661 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002662
2663 return MatchOperand_Success;
2664}
2665
Jim Grosbach251bf252011-08-10 21:56:18 +00002666ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2667parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2668 // Check for a post-index addressing register operand. Specifically:
2669 // am3offset := '+' register
2670 // | '-' register
2671 // | register
2672 // | # imm
2673 // | # + imm
2674 // | # - imm
2675
2676 // This method must return MatchOperand_NoMatch without consuming any tokens
2677 // in the case where there is no match, as other alternatives take other
2678 // parse methods.
2679 AsmToken Tok = Parser.getTok();
2680 SMLoc S = Tok.getLoc();
2681
2682 // Do immediates first, as we always parse those if we have a '#'.
2683 if (Parser.getTok().is(AsmToken::Hash)) {
2684 Parser.Lex(); // Eat the '#'.
2685 // Explicitly look for a '-', as we need to encode negative zero
2686 // differently.
2687 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2688 const MCExpr *Offset;
2689 if (getParser().ParseExpression(Offset))
2690 return MatchOperand_ParseFail;
2691 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2692 if (!CE) {
2693 Error(S, "constant expression expected");
2694 return MatchOperand_ParseFail;
2695 }
2696 SMLoc E = Tok.getLoc();
2697 // Negative zero is encoded as the flag value INT32_MIN.
2698 int32_t Val = CE->getValue();
2699 if (isNegative && Val == 0)
2700 Val = INT32_MIN;
2701
2702 Operands.push_back(
2703 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2704
2705 return MatchOperand_Success;
2706 }
2707
2708
2709 bool haveEaten = false;
2710 bool isAdd = true;
2711 int Reg = -1;
2712 if (Tok.is(AsmToken::Plus)) {
2713 Parser.Lex(); // Eat the '+' token.
2714 haveEaten = true;
2715 } else if (Tok.is(AsmToken::Minus)) {
2716 Parser.Lex(); // Eat the '-' token.
2717 isAdd = false;
2718 haveEaten = true;
2719 }
2720 if (Parser.getTok().is(AsmToken::Identifier))
2721 Reg = tryParseRegister();
2722 if (Reg == -1) {
2723 if (!haveEaten)
2724 return MatchOperand_NoMatch;
2725 Error(Parser.getTok().getLoc(), "register expected");
2726 return MatchOperand_ParseFail;
2727 }
2728 SMLoc E = Parser.getTok().getLoc();
2729
2730 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2731 0, S, E));
2732
2733 return MatchOperand_Success;
2734}
2735
Jim Grosbacha77295d2011-09-08 22:07:06 +00002736/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2737/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2738/// when they refer multiple MIOperands inside a single one.
2739bool ARMAsmParser::
2740cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2741 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2742 // Rt, Rt2
2743 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2744 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2745 // Create a writeback register dummy placeholder.
2746 Inst.addOperand(MCOperand::CreateReg(0));
2747 // addr
2748 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2749 // pred
2750 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2751 return true;
2752}
2753
2754/// cvtT2StrdPre - Convert parsed operands to MCInst.
2755/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2756/// when they refer multiple MIOperands inside a single one.
2757bool ARMAsmParser::
2758cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2759 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2760 // Create a writeback register dummy placeholder.
2761 Inst.addOperand(MCOperand::CreateReg(0));
2762 // Rt, Rt2
2763 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2764 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2765 // addr
2766 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2767 // pred
2768 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2769 return true;
2770}
2771
Jim Grosbacheeec0252011-09-08 00:39:19 +00002772/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2773/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2774/// when they refer multiple MIOperands inside a single one.
2775bool ARMAsmParser::
2776cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2777 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2778 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2779
2780 // Create a writeback register dummy placeholder.
2781 Inst.addOperand(MCOperand::CreateImm(0));
2782
2783 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2784 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2785 return true;
2786}
2787
Jim Grosbachee2c2a42011-09-16 21:55:56 +00002788/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2789/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2790/// when they refer multiple MIOperands inside a single one.
2791bool ARMAsmParser::
2792cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2793 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2794 // Create a writeback register dummy placeholder.
2795 Inst.addOperand(MCOperand::CreateImm(0));
2796 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2797 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2798 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2799 return true;
2800}
2801
Jim Grosbach1355cf12011-07-26 17:10:22 +00002802/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002803/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2804/// when they refer multiple MIOperands inside a single one.
2805bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002806cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002807 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2808 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2809
2810 // Create a writeback register dummy placeholder.
2811 Inst.addOperand(MCOperand::CreateImm(0));
2812
Jim Grosbach7ce05792011-08-03 23:50:40 +00002813 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002814 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2815 return true;
2816}
2817
Owen Anderson9ab0f252011-08-26 20:43:14 +00002818/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2819/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2820/// when they refer multiple MIOperands inside a single one.
2821bool ARMAsmParser::
2822cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2823 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2824 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2825
2826 // Create a writeback register dummy placeholder.
2827 Inst.addOperand(MCOperand::CreateImm(0));
2828
2829 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2830 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2831 return true;
2832}
2833
2834
Jim Grosbach548340c2011-08-11 19:22:40 +00002835/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2836/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2837/// when they refer multiple MIOperands inside a single one.
2838bool ARMAsmParser::
2839cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2840 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2841 // Create a writeback register dummy placeholder.
2842 Inst.addOperand(MCOperand::CreateImm(0));
2843 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2844 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2845 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2846 return true;
2847}
2848
Jim Grosbach1355cf12011-07-26 17:10:22 +00002849/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002850/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2851/// when they refer multiple MIOperands inside a single one.
2852bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002853cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002854 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2855 // Create a writeback register dummy placeholder.
2856 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00002857 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2858 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2859 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002860 return true;
2861}
2862
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00002863/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2864/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2865/// when they refer multiple MIOperands inside a single one.
2866bool ARMAsmParser::
2867cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2868 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2869 // Create a writeback register dummy placeholder.
2870 Inst.addOperand(MCOperand::CreateImm(0));
2871 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2872 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2873 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2874 return true;
2875}
2876
Jim Grosbach7ce05792011-08-03 23:50:40 +00002877/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2878/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2879/// when they refer multiple MIOperands inside a single one.
2880bool ARMAsmParser::
2881cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2882 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2883 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002884 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002885 // Create a writeback register dummy placeholder.
2886 Inst.addOperand(MCOperand::CreateImm(0));
2887 // addr
2888 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2889 // offset
2890 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2891 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002892 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2893 return true;
2894}
2895
Jim Grosbach7ce05792011-08-03 23:50:40 +00002896/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002897/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2898/// when they refer multiple MIOperands inside a single one.
2899bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002900cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2901 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2902 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00002903 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002904 // Create a writeback register dummy placeholder.
2905 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002906 // addr
2907 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2908 // offset
2909 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2910 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002911 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2912 return true;
2913}
2914
Jim Grosbach7ce05792011-08-03 23:50:40 +00002915/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002916/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2917/// when they refer multiple MIOperands inside a single one.
2918bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002919cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2920 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002921 // Create a writeback register dummy placeholder.
2922 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002923 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002924 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002925 // addr
2926 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2927 // offset
2928 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2929 // pred
2930 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2931 return true;
2932}
2933
2934/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
2935/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2936/// when they refer multiple MIOperands inside a single one.
2937bool ARMAsmParser::
2938cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2939 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2940 // Create a writeback register dummy placeholder.
2941 Inst.addOperand(MCOperand::CreateImm(0));
2942 // Rt
2943 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2944 // addr
2945 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2946 // offset
2947 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2948 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002949 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2950 return true;
2951}
2952
Jim Grosbach2fd2b872011-08-10 20:29:19 +00002953/// cvtLdrdPre - Convert parsed operands to MCInst.
2954/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2955/// when they refer multiple MIOperands inside a single one.
2956bool ARMAsmParser::
2957cvtLdrdPre(MCInst &Inst, unsigned Opcode,
2958 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2959 // Rt, Rt2
2960 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2961 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2962 // Create a writeback register dummy placeholder.
2963 Inst.addOperand(MCOperand::CreateImm(0));
2964 // addr
2965 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2966 // pred
2967 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2968 return true;
2969}
2970
Jim Grosbach14605d12011-08-11 20:28:23 +00002971/// cvtStrdPre - Convert parsed operands to MCInst.
2972/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2973/// when they refer multiple MIOperands inside a single one.
2974bool ARMAsmParser::
2975cvtStrdPre(MCInst &Inst, unsigned Opcode,
2976 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2977 // Create a writeback register dummy placeholder.
2978 Inst.addOperand(MCOperand::CreateImm(0));
2979 // Rt, Rt2
2980 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2981 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2982 // addr
2983 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2984 // pred
2985 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2986 return true;
2987}
2988
Jim Grosbach623a4542011-08-10 22:42:16 +00002989/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2990/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2991/// when they refer multiple MIOperands inside a single one.
2992bool ARMAsmParser::
2993cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2994 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2995 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2996 // Create a writeback register dummy placeholder.
2997 Inst.addOperand(MCOperand::CreateImm(0));
2998 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2999 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3000 return true;
3001}
3002
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003003/// cvtThumbMultiple- Convert parsed operands to MCInst.
3004/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3005/// when they refer multiple MIOperands inside a single one.
3006bool ARMAsmParser::
3007cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3008 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3009 // The second source operand must be the same register as the destination
3010 // operand.
3011 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003012 (((ARMOperand*)Operands[3])->getReg() !=
3013 ((ARMOperand*)Operands[5])->getReg()) &&
3014 (((ARMOperand*)Operands[3])->getReg() !=
3015 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003016 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003017 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003018 return false;
3019 }
3020 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3021 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3022 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003023 // If we have a three-operand form, use that, else the second source operand
3024 // is just the destination operand again.
3025 if (Operands.size() == 6)
3026 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3027 else
3028 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003029 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3030
3031 return true;
3032}
Jim Grosbach623a4542011-08-10 22:42:16 +00003033
Bill Wendlinge7176102010-11-06 22:36:58 +00003034/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003035/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003036bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003037parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003038 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003039 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003040 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003041 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003042 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003043
Sean Callanan18b83232010-01-19 21:44:56 +00003044 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003045 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003046 if (BaseRegNum == -1)
3047 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003048
Daniel Dunbar05710932011-01-18 05:34:17 +00003049 // The next token must either be a comma or a closing bracket.
3050 const AsmToken &Tok = Parser.getTok();
3051 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003052 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003053
Jim Grosbach7ce05792011-08-03 23:50:40 +00003054 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003055 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003056 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003057
Jim Grosbach7ce05792011-08-03 23:50:40 +00003058 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003059 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003060
Jim Grosbachfb12f352011-09-19 18:42:21 +00003061 // If there's a pre-indexing writeback marker, '!', just add it as a token
3062 // operand. It's rather odd, but syntactically valid.
3063 if (Parser.getTok().is(AsmToken::Exclaim)) {
3064 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3065 Parser.Lex(); // Eat the '!'.
3066 }
3067
Jim Grosbach7ce05792011-08-03 23:50:40 +00003068 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003069 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003070
Jim Grosbach7ce05792011-08-03 23:50:40 +00003071 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3072 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003073
Jim Grosbach57dcb852011-10-11 17:29:55 +00003074 // If we have a ':', it's an alignment specifier.
3075 if (Parser.getTok().is(AsmToken::Colon)) {
3076 Parser.Lex(); // Eat the ':'.
3077 E = Parser.getTok().getLoc();
3078
3079 const MCExpr *Expr;
3080 if (getParser().ParseExpression(Expr))
3081 return true;
3082
3083 // The expression has to be a constant. Memory references with relocations
3084 // don't come through here, as they use the <label> forms of the relevant
3085 // instructions.
3086 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3087 if (!CE)
3088 return Error (E, "constant expression expected");
3089
3090 unsigned Align = 0;
3091 switch (CE->getValue()) {
3092 default:
3093 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3094 case 64: Align = 8; break;
3095 case 128: Align = 16; break;
3096 case 256: Align = 32; break;
3097 }
3098
3099 // Now we should have the closing ']'
3100 E = Parser.getTok().getLoc();
3101 if (Parser.getTok().isNot(AsmToken::RBrac))
3102 return Error(E, "']' expected");
3103 Parser.Lex(); // Eat right bracket token.
3104
3105 // Don't worry about range checking the value here. That's handled by
3106 // the is*() predicates.
3107 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3108 ARM_AM::no_shift, 0, Align,
3109 false, S, E));
3110
3111 // If there's a pre-indexing writeback marker, '!', just add it as a token
3112 // operand.
3113 if (Parser.getTok().is(AsmToken::Exclaim)) {
3114 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3115 Parser.Lex(); // Eat the '!'.
3116 }
3117
3118 return false;
3119 }
3120
3121 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003122 // offset.
3123 if (Parser.getTok().is(AsmToken::Hash)) {
3124 Parser.Lex(); // Eat the '#'.
3125 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003126
Owen Anderson0da10cf2011-08-29 19:36:44 +00003127 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003128 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003129 if (getParser().ParseExpression(Offset))
3130 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003131
3132 // The expression has to be a constant. Memory references with relocations
3133 // don't come through here, as they use the <label> forms of the relevant
3134 // instructions.
3135 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3136 if (!CE)
3137 return Error (E, "constant expression expected");
3138
Owen Anderson0da10cf2011-08-29 19:36:44 +00003139 // If the constant was #-0, represent it as INT32_MIN.
3140 int32_t Val = CE->getValue();
3141 if (isNegative && Val == 0)
3142 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3143
Jim Grosbach7ce05792011-08-03 23:50:40 +00003144 // Now we should have the closing ']'
3145 E = Parser.getTok().getLoc();
3146 if (Parser.getTok().isNot(AsmToken::RBrac))
3147 return Error(E, "']' expected");
3148 Parser.Lex(); // Eat right bracket token.
3149
3150 // Don't worry about range checking the value here. That's handled by
3151 // the is*() predicates.
3152 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003153 ARM_AM::no_shift, 0, 0,
3154 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003155
3156 // If there's a pre-indexing writeback marker, '!', just add it as a token
3157 // operand.
3158 if (Parser.getTok().is(AsmToken::Exclaim)) {
3159 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3160 Parser.Lex(); // Eat the '!'.
3161 }
3162
3163 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003164 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003165
3166 // The register offset is optionally preceded by a '+' or '-'
3167 bool isNegative = false;
3168 if (Parser.getTok().is(AsmToken::Minus)) {
3169 isNegative = true;
3170 Parser.Lex(); // Eat the '-'.
3171 } else if (Parser.getTok().is(AsmToken::Plus)) {
3172 // Nothing to do.
3173 Parser.Lex(); // Eat the '+'.
3174 }
3175
3176 E = Parser.getTok().getLoc();
3177 int OffsetRegNum = tryParseRegister();
3178 if (OffsetRegNum == -1)
3179 return Error(E, "register expected");
3180
3181 // If there's a shift operator, handle it.
3182 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003183 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003184 if (Parser.getTok().is(AsmToken::Comma)) {
3185 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003186 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003187 return true;
3188 }
3189
3190 // Now we should have the closing ']'
3191 E = Parser.getTok().getLoc();
3192 if (Parser.getTok().isNot(AsmToken::RBrac))
3193 return Error(E, "']' expected");
3194 Parser.Lex(); // Eat right bracket token.
3195
3196 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003197 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003198 S, E));
3199
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003200 // If there's a pre-indexing writeback marker, '!', just add it as a token
3201 // operand.
3202 if (Parser.getTok().is(AsmToken::Exclaim)) {
3203 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3204 Parser.Lex(); // Eat the '!'.
3205 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003206
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003207 return false;
3208}
3209
Jim Grosbach7ce05792011-08-03 23:50:40 +00003210/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003211/// ( lsl | lsr | asr | ror ) , # shift_amount
3212/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003213/// return true if it parses a shift otherwise it returns false.
3214bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3215 unsigned &Amount) {
3216 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003217 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003218 if (Tok.isNot(AsmToken::Identifier))
3219 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003220 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003221 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003222 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003223 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003224 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003225 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003226 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003227 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003228 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003229 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003230 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003231 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003232 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003233 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003234
Jim Grosbach7ce05792011-08-03 23:50:40 +00003235 // rrx stands alone.
3236 Amount = 0;
3237 if (St != ARM_AM::rrx) {
3238 Loc = Parser.getTok().getLoc();
3239 // A '#' and a shift amount.
3240 const AsmToken &HashTok = Parser.getTok();
3241 if (HashTok.isNot(AsmToken::Hash))
3242 return Error(HashTok.getLoc(), "'#' expected");
3243 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003244
Jim Grosbach7ce05792011-08-03 23:50:40 +00003245 const MCExpr *Expr;
3246 if (getParser().ParseExpression(Expr))
3247 return true;
3248 // Range check the immediate.
3249 // lsl, ror: 0 <= imm <= 31
3250 // lsr, asr: 0 <= imm <= 32
3251 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3252 if (!CE)
3253 return Error(Loc, "shift amount must be an immediate");
3254 int64_t Imm = CE->getValue();
3255 if (Imm < 0 ||
3256 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3257 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3258 return Error(Loc, "immediate shift value out of range");
3259 Amount = Imm;
3260 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003261
3262 return false;
3263}
3264
Jim Grosbach9d390362011-10-03 23:38:36 +00003265/// parseFPImm - A floating point immediate expression operand.
3266ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3267parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3268 SMLoc S = Parser.getTok().getLoc();
3269
3270 if (Parser.getTok().isNot(AsmToken::Hash))
3271 return MatchOperand_NoMatch;
3272 Parser.Lex(); // Eat the '#'.
3273
3274 // Handle negation, as that still comes through as a separate token.
3275 bool isNegative = false;
3276 if (Parser.getTok().is(AsmToken::Minus)) {
3277 isNegative = true;
3278 Parser.Lex();
3279 }
3280 const AsmToken &Tok = Parser.getTok();
3281 if (Tok.is(AsmToken::Real)) {
3282 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3283 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3284 // If we had a '-' in front, toggle the sign bit.
3285 IntVal ^= (uint64_t)isNegative << 63;
3286 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3287 Parser.Lex(); // Eat the token.
3288 if (Val == -1) {
3289 TokError("floating point value out of range");
3290 return MatchOperand_ParseFail;
3291 }
3292 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3293 return MatchOperand_Success;
3294 }
3295 if (Tok.is(AsmToken::Integer)) {
3296 int64_t Val = Tok.getIntVal();
3297 Parser.Lex(); // Eat the token.
3298 if (Val > 255 || Val < 0) {
3299 TokError("encoded floating point value out of range");
3300 return MatchOperand_ParseFail;
3301 }
3302 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3303 return MatchOperand_Success;
3304 }
3305
3306 TokError("invalid floating point immediate");
3307 return MatchOperand_ParseFail;
3308}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003309/// Parse a arm instruction operand. For now this parses the operand regardless
3310/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003311bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003312 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003313 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003314
3315 // Check if the current operand has a custom associated parser, if so, try to
3316 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003317 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3318 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003319 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003320 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3321 // there was a match, but an error occurred, in which case, just return that
3322 // the operand parsing failed.
3323 if (ResTy == MatchOperand_ParseFail)
3324 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003325
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003326 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003327 default:
3328 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003329 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003330 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003331 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003332 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003333 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003334 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003335 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003336 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003337 else if (Res == -1) // irrecoverable error
3338 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003339 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3340 S = Parser.getTok().getLoc();
3341 Parser.Lex();
3342 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3343 return false;
3344 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003345
3346 // Fall though for the Identifier case that is not a register or a
3347 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003348 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003349 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3350 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003351 // This was not a register so parse other operands that start with an
3352 // identifier (like labels) as expressions and create them as immediates.
3353 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003354 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003355 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003356 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003357 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003358 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3359 return false;
3360 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003361 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003362 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003363 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003364 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003365 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003366 // #42 -> immediate.
3367 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003368 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003369 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003370 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003371 const MCExpr *ImmVal;
3372 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003373 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003374 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3375 if (!CE) {
3376 Error(S, "constant expression expected");
3377 return MatchOperand_ParseFail;
3378 }
3379 int32_t Val = CE->getValue();
3380 if (isNegative && Val == 0)
3381 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003382 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003383 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3384 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003385 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003386 case AsmToken::Colon: {
3387 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003388 // FIXME: Check it's an expression prefix,
3389 // e.g. (FOO - :lower16:BAR) isn't legal.
3390 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003391 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003392 return true;
3393
Evan Cheng75972122011-01-13 07:58:56 +00003394 const MCExpr *SubExprVal;
3395 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003396 return true;
3397
Evan Cheng75972122011-01-13 07:58:56 +00003398 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3399 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003400 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003401 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003402 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003403 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003404 }
3405}
3406
Jim Grosbach1355cf12011-07-26 17:10:22 +00003407// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003408// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003409bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003410 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003411
3412 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003413 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003414 Parser.Lex(); // Eat ':'
3415
3416 if (getLexer().isNot(AsmToken::Identifier)) {
3417 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3418 return true;
3419 }
3420
3421 StringRef IDVal = Parser.getTok().getIdentifier();
3422 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003423 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003424 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003425 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003426 } else {
3427 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3428 return true;
3429 }
3430 Parser.Lex();
3431
3432 if (getLexer().isNot(AsmToken::Colon)) {
3433 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3434 return true;
3435 }
3436 Parser.Lex(); // Eat the last ':'
3437 return false;
3438}
3439
Daniel Dunbar352e1482011-01-11 15:59:50 +00003440/// \brief Given a mnemonic, split out possible predication code and carry
3441/// setting letters to form a canonical mnemonic and flags.
3442//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003443// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003444// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003445StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003446 unsigned &PredicationCode,
3447 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003448 unsigned &ProcessorIMod,
3449 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003450 PredicationCode = ARMCC::AL;
3451 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003452 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003453
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003454 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003455 //
3456 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003457 if ((Mnemonic == "movs" && isThumb()) ||
3458 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3459 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3460 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3461 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3462 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3463 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3464 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003465 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003466
Jim Grosbach3f00e312011-07-11 17:09:57 +00003467 // First, split out any predication code. Ignore mnemonics we know aren't
3468 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003469 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003470 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003471 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003472 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003473 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3474 .Case("eq", ARMCC::EQ)
3475 .Case("ne", ARMCC::NE)
3476 .Case("hs", ARMCC::HS)
3477 .Case("cs", ARMCC::HS)
3478 .Case("lo", ARMCC::LO)
3479 .Case("cc", ARMCC::LO)
3480 .Case("mi", ARMCC::MI)
3481 .Case("pl", ARMCC::PL)
3482 .Case("vs", ARMCC::VS)
3483 .Case("vc", ARMCC::VC)
3484 .Case("hi", ARMCC::HI)
3485 .Case("ls", ARMCC::LS)
3486 .Case("ge", ARMCC::GE)
3487 .Case("lt", ARMCC::LT)
3488 .Case("gt", ARMCC::GT)
3489 .Case("le", ARMCC::LE)
3490 .Case("al", ARMCC::AL)
3491 .Default(~0U);
3492 if (CC != ~0U) {
3493 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3494 PredicationCode = CC;
3495 }
Bill Wendling52925b62010-10-29 23:50:21 +00003496 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003497
Daniel Dunbar352e1482011-01-11 15:59:50 +00003498 // Next, determine if we have a carry setting bit. We explicitly ignore all
3499 // the instructions we know end in 's'.
3500 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003501 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003502 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3503 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3504 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003505 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3506 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003507 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3508 CarrySetting = true;
3509 }
3510
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003511 // The "cps" instruction can have a interrupt mode operand which is glued into
3512 // the mnemonic. Check if this is the case, split it and parse the imod op
3513 if (Mnemonic.startswith("cps")) {
3514 // Split out any imod code.
3515 unsigned IMod =
3516 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3517 .Case("ie", ARM_PROC::IE)
3518 .Case("id", ARM_PROC::ID)
3519 .Default(~0U);
3520 if (IMod != ~0U) {
3521 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3522 ProcessorIMod = IMod;
3523 }
3524 }
3525
Jim Grosbach89df9962011-08-26 21:43:41 +00003526 // The "it" instruction has the condition mask on the end of the mnemonic.
3527 if (Mnemonic.startswith("it")) {
3528 ITMask = Mnemonic.slice(2, Mnemonic.size());
3529 Mnemonic = Mnemonic.slice(0, 2);
3530 }
3531
Daniel Dunbar352e1482011-01-11 15:59:50 +00003532 return Mnemonic;
3533}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003534
3535/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3536/// inclusion of carry set or predication code operands.
3537//
3538// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003539void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003540getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003541 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003542 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3543 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003544 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003545 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003546 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003547 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003548 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003549 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003550 Mnemonic == "mla" || Mnemonic == "smlal" ||
3551 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003552 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003553 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003554 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003555
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003556 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3557 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3558 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3559 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003560 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3561 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003562 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003563 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3564 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3565 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003566 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3567 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003568 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003569 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003570 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003571 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003572
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003573 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003574 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003575 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003576 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003577 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003578}
3579
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003580bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3581 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003582 // FIXME: This is all horribly hacky. We really need a better way to deal
3583 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003584
3585 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3586 // another does not. Specifically, the MOVW instruction does not. So we
3587 // special case it here and remove the defaulted (non-setting) cc_out
3588 // operand if that's the instruction we're trying to match.
3589 //
3590 // We do this as post-processing of the explicit operands rather than just
3591 // conditionally adding the cc_out in the first place because we need
3592 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003593 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003594 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3595 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3596 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3597 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003598
3599 // Register-register 'add' for thumb does not have a cc_out operand
3600 // when there are only two register operands.
3601 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3602 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3603 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3604 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3605 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003606 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003607 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3608 // have to check the immediate range here since Thumb2 has a variant
3609 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003610 if (((isThumb() && Mnemonic == "add") ||
3611 (isThumbTwo() && Mnemonic == "sub")) &&
3612 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003613 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3614 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3615 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003616 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3617 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3618 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003619 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003620 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3621 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003622 // selecting via the generic "add" mnemonic, so to know that we
3623 // should remove the cc_out operand, we have to explicitly check that
3624 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003625 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3626 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003627 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3628 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3629 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3630 // Nest conditions rather than one big 'if' statement for readability.
3631 //
3632 // If either register is a high reg, it's either one of the SP
3633 // variants (handled above) or a 32-bit encoding, so we just
3634 // check against T3.
3635 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3636 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3637 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3638 return false;
3639 // If both registers are low, we're in an IT block, and the immediate is
3640 // in range, we should use encoding T1 instead, which has a cc_out.
3641 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003642 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003643 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3644 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3645 return false;
3646
3647 // Otherwise, we use encoding T4, which does not have a cc_out
3648 // operand.
3649 return true;
3650 }
3651
Jim Grosbach64944f42011-09-14 21:00:40 +00003652 // The thumb2 multiply instruction doesn't have a CCOut register, so
3653 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3654 // use the 16-bit encoding or not.
3655 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3656 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3657 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3658 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3659 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3660 // If the registers aren't low regs, the destination reg isn't the
3661 // same as one of the source regs, or the cc_out operand is zero
3662 // outside of an IT block, we have to use the 32-bit encoding, so
3663 // remove the cc_out operand.
3664 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3665 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3666 !inITBlock() ||
3667 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3668 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3669 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3670 static_cast<ARMOperand*>(Operands[4])->getReg())))
3671 return true;
3672
3673
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003674
Jim Grosbachf69c8042011-08-24 21:42:27 +00003675 // Register-register 'add/sub' for thumb does not have a cc_out operand
3676 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3677 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3678 // right, this will result in better diagnostics (which operand is off)
3679 // anyway.
3680 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3681 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003682 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3683 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3684 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3685 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003686
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003687 return false;
3688}
3689
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003690/// Parse an arm instruction mnemonic followed by its operands.
3691bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3692 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3693 // Create the leading tokens for the mnemonic, split by '.' characters.
3694 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003695 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003696
Daniel Dunbar352e1482011-01-11 15:59:50 +00003697 // Split out the predication code and carry setting flag from the mnemonic.
3698 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003699 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003700 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003701 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003702 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003703 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003704
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003705 // In Thumb1, only the branch (B) instruction can be predicated.
3706 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3707 Parser.EatToEndOfStatement();
3708 return Error(NameLoc, "conditional execution not supported in Thumb1");
3709 }
3710
Jim Grosbachffa32252011-07-19 19:13:28 +00003711 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3712
Jim Grosbach89df9962011-08-26 21:43:41 +00003713 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3714 // is the mask as it will be for the IT encoding if the conditional
3715 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3716 // where the conditional bit0 is zero, the instruction post-processing
3717 // will adjust the mask accordingly.
3718 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003719 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3720 if (ITMask.size() > 3) {
3721 Parser.EatToEndOfStatement();
3722 return Error(Loc, "too many conditions on IT instruction");
3723 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003724 unsigned Mask = 8;
3725 for (unsigned i = ITMask.size(); i != 0; --i) {
3726 char pos = ITMask[i - 1];
3727 if (pos != 't' && pos != 'e') {
3728 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003729 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00003730 }
3731 Mask >>= 1;
3732 if (ITMask[i - 1] == 't')
3733 Mask |= 8;
3734 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003735 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00003736 }
3737
Jim Grosbachffa32252011-07-19 19:13:28 +00003738 // FIXME: This is all a pretty gross hack. We should automatically handle
3739 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00003740
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003741 // Next, add the CCOut and ConditionCode operands, if needed.
3742 //
3743 // For mnemonics which can ever incorporate a carry setting bit or predication
3744 // code, our matching model involves us always generating CCOut and
3745 // ConditionCode operands to match the mnemonic "as written" and then we let
3746 // the matcher deal with finding the right instruction or generating an
3747 // appropriate error.
3748 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003749 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003750
Jim Grosbach33c16a22011-07-14 22:04:21 +00003751 // If we had a carry-set on an instruction that can't do that, issue an
3752 // error.
3753 if (!CanAcceptCarrySet && CarrySetting) {
3754 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00003755 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00003756 "' can not set flags, but 's' suffix specified");
3757 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003758 // If we had a predication code on an instruction that can't do that, issue an
3759 // error.
3760 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3761 Parser.EatToEndOfStatement();
3762 return Error(NameLoc, "instruction '" + Mnemonic +
3763 "' is not predicable, but condition code specified");
3764 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00003765
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003766 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003767 if (CanAcceptCarrySet) {
3768 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003769 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003770 Loc));
3771 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003772
3773 // Add the predication code operand, if necessary.
3774 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003775 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3776 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003777 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003778 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003779 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003780
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003781 // Add the processor imod operand, if necessary.
3782 if (ProcessorIMod) {
3783 Operands.push_back(ARMOperand::CreateImm(
3784 MCConstantExpr::Create(ProcessorIMod, getContext()),
3785 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003786 }
3787
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003788 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00003789 while (Next != StringRef::npos) {
3790 Start = Next;
3791 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003792 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003793
Jim Grosbach4d23e992011-08-24 22:19:48 +00003794 // For now, we're only parsing Thumb1 (for the most part), so
3795 // just ignore ".n" qualifiers. We'll use them to restrict
3796 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00003797 if (ExtraToken != ".n") {
3798 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3799 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3800 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00003801 }
3802
3803 // Read the remaining operands.
3804 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003805 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003806 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003807 Parser.EatToEndOfStatement();
3808 return true;
3809 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003810
3811 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00003812 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003813
3814 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003815 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003816 Parser.EatToEndOfStatement();
3817 return true;
3818 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003819 }
3820 }
Jim Grosbach16c74252010-10-29 14:46:02 +00003821
Chris Lattnercbf8a982010-09-11 16:18:25 +00003822 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00003823 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00003824 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00003825 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00003826 }
Bill Wendling146018f2010-11-06 21:42:12 +00003827
Chris Lattner34e53142010-09-08 05:10:46 +00003828 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00003829
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003830 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3831 // do and don't have a cc_out optional-def operand. With some spot-checks
3832 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003833 // parse and adjust accordingly before actually matching. We shouldn't ever
3834 // try to remove a cc_out operand that was explicitly set on the the
3835 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3836 // table driven matcher doesn't fit well with the ARM instruction set.
3837 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00003838 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3839 Operands.erase(Operands.begin() + 1);
3840 delete Op;
3841 }
3842
Jim Grosbachcf121c32011-07-28 21:57:55 +00003843 // ARM mode 'blx' need special handling, as the register operand version
3844 // is predicable, but the label operand version is not. So, we can't rely
3845 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00003846 // a k_CondCode operand in the list. If we're trying to match the label
3847 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00003848 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3849 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3850 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3851 Operands.erase(Operands.begin() + 1);
3852 delete Op;
3853 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00003854
3855 // The vector-compare-to-zero instructions have a literal token "#0" at
3856 // the end that comes to here as an immediate operand. Convert it to a
3857 // token to play nicely with the matcher.
3858 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3859 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3860 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3861 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3862 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3863 if (CE && CE->getValue() == 0) {
3864 Operands.erase(Operands.begin() + 5);
3865 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3866 delete Op;
3867 }
3868 }
Jim Grosbach68259142011-10-03 22:30:24 +00003869 // VCMP{E} does the same thing, but with a different operand count.
3870 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3871 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3872 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3873 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3874 if (CE && CE->getValue() == 0) {
3875 Operands.erase(Operands.begin() + 4);
3876 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3877 delete Op;
3878 }
3879 }
Jim Grosbach934755a2011-08-22 23:47:13 +00003880 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
3881 // end. Convert it to a token here.
3882 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
3883 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3884 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3885 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3886 if (CE && CE->getValue() == 0) {
3887 Operands.erase(Operands.begin() + 5);
3888 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3889 delete Op;
3890 }
3891 }
3892
Chris Lattner98986712010-01-14 22:21:20 +00003893 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00003894}
3895
Jim Grosbach189610f2011-07-26 18:25:39 +00003896// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00003897
3898// return 'true' if register list contains non-low GPR registers,
3899// 'false' otherwise. If Reg is in the register list or is HiReg, set
3900// 'containsReg' to true.
3901static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
3902 unsigned HiReg, bool &containsReg) {
3903 containsReg = false;
3904 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3905 unsigned OpReg = Inst.getOperand(i).getReg();
3906 if (OpReg == Reg)
3907 containsReg = true;
3908 // Anything other than a low register isn't legal here.
3909 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
3910 return true;
3911 }
3912 return false;
3913}
3914
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003915// Check if the specified regisgter is in the register list of the inst,
3916// starting at the indicated operand number.
3917static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
3918 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3919 unsigned OpReg = Inst.getOperand(i).getReg();
3920 if (OpReg == Reg)
3921 return true;
3922 }
3923 return false;
3924}
3925
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003926// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
3927// the ARMInsts array) instead. Getting that here requires awkward
3928// API changes, though. Better way?
3929namespace llvm {
3930extern MCInstrDesc ARMInsts[];
3931}
3932static MCInstrDesc &getInstDesc(unsigned Opcode) {
3933 return ARMInsts[Opcode];
3934}
3935
Jim Grosbach189610f2011-07-26 18:25:39 +00003936// FIXME: We would really like to be able to tablegen'erate this.
3937bool ARMAsmParser::
3938validateInstruction(MCInst &Inst,
3939 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003940 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3941 SMLoc Loc = Operands[0]->getStartLoc();
3942 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00003943 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
3944 // being allowed in IT blocks, but not being predicable. It just always
3945 // executes.
3946 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003947 unsigned bit = 1;
3948 if (ITState.FirstCond)
3949 ITState.FirstCond = false;
3950 else
Jim Grosbacha1109882011-09-02 23:22:08 +00003951 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003952 // The instruction must be predicable.
3953 if (!MCID.isPredicable())
3954 return Error(Loc, "instructions in IT block must be predicable");
3955 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
3956 unsigned ITCond = bit ? ITState.Cond :
3957 ARMCC::getOppositeCondition(ITState.Cond);
3958 if (Cond != ITCond) {
3959 // Find the condition code Operand to get its SMLoc information.
3960 SMLoc CondLoc;
3961 for (unsigned i = 1; i < Operands.size(); ++i)
3962 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
3963 CondLoc = Operands[i]->getStartLoc();
3964 return Error(CondLoc, "incorrect condition in IT block; got '" +
3965 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
3966 "', but expected '" +
3967 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
3968 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00003969 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003970 } else if (isThumbTwo() && MCID.isPredicable() &&
3971 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00003972 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
3973 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003974 return Error(Loc, "predicated instructions must be in IT block");
3975
Jim Grosbach189610f2011-07-26 18:25:39 +00003976 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003977 case ARM::LDRD:
3978 case ARM::LDRD_PRE:
3979 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00003980 case ARM::LDREXD: {
3981 // Rt2 must be Rt + 1.
3982 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3983 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3984 if (Rt2 != Rt + 1)
3985 return Error(Operands[3]->getStartLoc(),
3986 "destination operands must be sequential");
3987 return false;
3988 }
Jim Grosbach14605d12011-08-11 20:28:23 +00003989 case ARM::STRD: {
3990 // Rt2 must be Rt + 1.
3991 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3992 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3993 if (Rt2 != Rt + 1)
3994 return Error(Operands[3]->getStartLoc(),
3995 "source operands must be sequential");
3996 return false;
3997 }
Jim Grosbach53642c52011-08-10 20:49:18 +00003998 case ARM::STRD_PRE:
3999 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004000 case ARM::STREXD: {
4001 // Rt2 must be Rt + 1.
4002 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4003 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4004 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004005 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004006 "source operands must be sequential");
4007 return false;
4008 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004009 case ARM::SBFX:
4010 case ARM::UBFX: {
4011 // width must be in range [1, 32-lsb]
4012 unsigned lsb = Inst.getOperand(2).getImm();
4013 unsigned widthm1 = Inst.getOperand(3).getImm();
4014 if (widthm1 >= 32 - lsb)
4015 return Error(Operands[5]->getStartLoc(),
4016 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004017 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004018 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004019 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004020 // If we're parsing Thumb2, the .w variant is available and handles
4021 // most cases that are normally illegal for a Thumb1 LDM
4022 // instruction. We'll make the transformation in processInstruction()
4023 // if necessary.
4024 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004025 // Thumb LDM instructions are writeback iff the base register is not
4026 // in the register list.
4027 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004028 bool hasWritebackToken =
4029 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4030 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004031 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004032 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004033 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4034 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004035 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004036 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004037 return Error(Operands[2]->getStartLoc(),
4038 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004039 // If we should not have writeback, there must not be a '!'. This is
4040 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004041 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004042 return Error(Operands[3]->getStartLoc(),
4043 "writeback operator '!' not allowed when base register "
4044 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004045
4046 break;
4047 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004048 case ARM::t2LDMIA_UPD: {
4049 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4050 return Error(Operands[4]->getStartLoc(),
4051 "writeback operator '!' not allowed when base register "
4052 "in register list");
4053 break;
4054 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004055 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004056 bool listContainsBase;
4057 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4058 return Error(Operands[2]->getStartLoc(),
4059 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004060 break;
4061 }
4062 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004063 bool listContainsBase;
4064 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4065 return Error(Operands[2]->getStartLoc(),
4066 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004067 break;
4068 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004069 case ARM::tSTMIA_UPD: {
4070 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004071 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004072 return Error(Operands[4]->getStartLoc(),
4073 "registers must be in range r0-r7");
4074 break;
4075 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004076 }
4077
4078 return false;
4079}
4080
Jim Grosbachf8fce712011-08-11 17:35:48 +00004081void ARMAsmParser::
4082processInstruction(MCInst &Inst,
4083 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4084 switch (Inst.getOpcode()) {
4085 case ARM::LDMIA_UPD:
4086 // If this is a load of a single register via a 'pop', then we should use
4087 // a post-indexed LDR instruction instead, per the ARM ARM.
4088 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4089 Inst.getNumOperands() == 5) {
4090 MCInst TmpInst;
4091 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4092 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4093 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4094 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4095 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4096 TmpInst.addOperand(MCOperand::CreateImm(4));
4097 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4098 TmpInst.addOperand(Inst.getOperand(3));
4099 Inst = TmpInst;
4100 }
4101 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004102 case ARM::STMDB_UPD:
4103 // If this is a store of a single register via a 'push', then we should use
4104 // a pre-indexed STR instruction instead, per the ARM ARM.
4105 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4106 Inst.getNumOperands() == 5) {
4107 MCInst TmpInst;
4108 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4109 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4110 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4111 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4112 TmpInst.addOperand(MCOperand::CreateImm(-4));
4113 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4114 TmpInst.addOperand(Inst.getOperand(3));
4115 Inst = TmpInst;
4116 }
4117 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004118 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004119 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4120 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4121 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4122 // to encoding T1 if <Rd> is omitted."
4123 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004124 Inst.setOpcode(ARM::tADDi3);
4125 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004126 case ARM::tSUBi8:
4127 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4128 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4129 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4130 // to encoding T1 if <Rd> is omitted."
4131 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4132 Inst.setOpcode(ARM::tSUBi3);
4133 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004134 case ARM::tB:
4135 // A Thumb conditional branch outside of an IT block is a tBcc.
4136 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4137 Inst.setOpcode(ARM::tBcc);
4138 break;
4139 case ARM::t2B:
4140 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4141 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4142 Inst.setOpcode(ARM::t2Bcc);
4143 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004144 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004145 // If the conditional is AL or we're in an IT block, we really want t2B.
4146 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004147 Inst.setOpcode(ARM::t2B);
4148 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004149 case ARM::tBcc:
4150 // If the conditional is AL, we really want tB.
4151 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4152 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004153 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004154 case ARM::tLDMIA: {
4155 // If the register list contains any high registers, or if the writeback
4156 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4157 // instead if we're in Thumb2. Otherwise, this should have generated
4158 // an error in validateInstruction().
4159 unsigned Rn = Inst.getOperand(0).getReg();
4160 bool hasWritebackToken =
4161 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4162 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4163 bool listContainsBase;
4164 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4165 (!listContainsBase && !hasWritebackToken) ||
4166 (listContainsBase && hasWritebackToken)) {
4167 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4168 assert (isThumbTwo());
4169 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4170 // If we're switching to the updating version, we need to insert
4171 // the writeback tied operand.
4172 if (hasWritebackToken)
4173 Inst.insert(Inst.begin(),
4174 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4175 }
4176 break;
4177 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004178 case ARM::tSTMIA_UPD: {
4179 // If the register list contains any high registers, we need to use
4180 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4181 // should have generated an error in validateInstruction().
4182 unsigned Rn = Inst.getOperand(0).getReg();
4183 bool listContainsBase;
4184 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4185 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4186 assert (isThumbTwo());
4187 Inst.setOpcode(ARM::t2STMIA_UPD);
4188 }
4189 break;
4190 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004191 case ARM::t2MOVi: {
4192 // If we can use the 16-bit encoding and the user didn't explicitly
4193 // request the 32-bit variant, transform it here.
4194 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4195 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004196 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4197 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4198 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004199 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4200 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4201 // The operands aren't in the same order for tMOVi8...
4202 MCInst TmpInst;
4203 TmpInst.setOpcode(ARM::tMOVi8);
4204 TmpInst.addOperand(Inst.getOperand(0));
4205 TmpInst.addOperand(Inst.getOperand(4));
4206 TmpInst.addOperand(Inst.getOperand(1));
4207 TmpInst.addOperand(Inst.getOperand(2));
4208 TmpInst.addOperand(Inst.getOperand(3));
4209 Inst = TmpInst;
4210 }
4211 break;
4212 }
4213 case ARM::t2MOVr: {
4214 // If we can use the 16-bit encoding and the user didn't explicitly
4215 // request the 32-bit variant, transform it here.
4216 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4217 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4218 Inst.getOperand(2).getImm() == ARMCC::AL &&
4219 Inst.getOperand(4).getReg() == ARM::CPSR &&
4220 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4221 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4222 // The operands aren't the same for tMOV[S]r... (no cc_out)
4223 MCInst TmpInst;
4224 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4225 TmpInst.addOperand(Inst.getOperand(0));
4226 TmpInst.addOperand(Inst.getOperand(1));
4227 TmpInst.addOperand(Inst.getOperand(2));
4228 TmpInst.addOperand(Inst.getOperand(3));
4229 Inst = TmpInst;
4230 }
4231 break;
4232 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004233 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004234 case ARM::t2SXTB:
4235 case ARM::t2UXTH:
4236 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004237 // If we can use the 16-bit encoding and the user didn't explicitly
4238 // request the 32-bit variant, transform it here.
4239 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4240 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4241 Inst.getOperand(2).getImm() == 0 &&
4242 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4243 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004244 unsigned NewOpc;
4245 switch (Inst.getOpcode()) {
4246 default: llvm_unreachable("Illegal opcode!");
4247 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4248 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4249 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4250 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4251 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004252 // The operands aren't the same for thumb1 (no rotate operand).
4253 MCInst TmpInst;
4254 TmpInst.setOpcode(NewOpc);
4255 TmpInst.addOperand(Inst.getOperand(0));
4256 TmpInst.addOperand(Inst.getOperand(1));
4257 TmpInst.addOperand(Inst.getOperand(3));
4258 TmpInst.addOperand(Inst.getOperand(4));
4259 Inst = TmpInst;
4260 }
4261 break;
4262 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004263 case ARM::t2IT: {
4264 // The mask bits for all but the first condition are represented as
4265 // the low bit of the condition code value implies 't'. We currently
4266 // always have 1 implies 't', so XOR toggle the bits if the low bit
4267 // of the condition code is zero. The encoding also expects the low
4268 // bit of the condition to be encoded as bit 4 of the mask operand,
4269 // so mask that in if needed
4270 MCOperand &MO = Inst.getOperand(1);
4271 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004272 unsigned OrigMask = Mask;
4273 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004274 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004275 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4276 for (unsigned i = 3; i != TZ; --i)
4277 Mask ^= 1 << i;
4278 } else
4279 Mask |= 0x10;
4280 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004281
4282 // Set up the IT block state according to the IT instruction we just
4283 // matched.
4284 assert(!inITBlock() && "nested IT blocks?!");
4285 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4286 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4287 ITState.CurPosition = 0;
4288 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004289 break;
4290 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004291 }
4292}
4293
Jim Grosbach47a0d522011-08-16 20:45:50 +00004294unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4295 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4296 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004297 unsigned Opc = Inst.getOpcode();
4298 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004299 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4300 assert(MCID.hasOptionalDef() &&
4301 "optionally flag setting instruction missing optional def operand");
4302 assert(MCID.NumOperands == Inst.getNumOperands() &&
4303 "operand count mismatch!");
4304 // Find the optional-def operand (cc_out).
4305 unsigned OpNo;
4306 for (OpNo = 0;
4307 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4308 ++OpNo)
4309 ;
4310 // If we're parsing Thumb1, reject it completely.
4311 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4312 return Match_MnemonicFail;
4313 // If we're parsing Thumb2, which form is legal depends on whether we're
4314 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004315 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4316 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004317 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004318 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4319 inITBlock())
4320 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004321 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004322 // Some high-register supporting Thumb1 encodings only allow both registers
4323 // to be from r0-r7 when in Thumb2.
4324 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4325 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4326 isARMLowRegister(Inst.getOperand(2).getReg()))
4327 return Match_RequiresThumb2;
4328 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004329 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004330 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4331 isARMLowRegister(Inst.getOperand(1).getReg()))
4332 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004333 return Match_Success;
4334}
4335
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004336bool ARMAsmParser::
4337MatchAndEmitInstruction(SMLoc IDLoc,
4338 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4339 MCStreamer &Out) {
4340 MCInst Inst;
4341 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004342 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004343 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004344 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004345 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004346 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004347 // Context sensitive operand constraints aren't handled by the matcher,
4348 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004349 if (validateInstruction(Inst, Operands)) {
4350 // Still progress the IT block, otherwise one wrong condition causes
4351 // nasty cascading errors.
4352 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004353 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004354 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004355
Jim Grosbachf8fce712011-08-11 17:35:48 +00004356 // Some instructions need post-processing to, for example, tweak which
4357 // encoding is selected.
4358 processInstruction(Inst, Operands);
4359
Jim Grosbacha1109882011-09-02 23:22:08 +00004360 // Only move forward at the very end so that everything in validate
4361 // and process gets a consistent answer about whether we're in an IT
4362 // block.
4363 forwardITPosition();
4364
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004365 Out.EmitInstruction(Inst);
4366 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004367 case Match_MissingFeature:
4368 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4369 return true;
4370 case Match_InvalidOperand: {
4371 SMLoc ErrorLoc = IDLoc;
4372 if (ErrorInfo != ~0U) {
4373 if (ErrorInfo >= Operands.size())
4374 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004375
Chris Lattnere73d4f82010-10-28 21:41:58 +00004376 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4377 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4378 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004379
Chris Lattnere73d4f82010-10-28 21:41:58 +00004380 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004381 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004382 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004383 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004384 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004385 // The converter function will have already emited a diagnostic.
4386 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004387 case Match_RequiresNotITBlock:
4388 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004389 case Match_RequiresITBlock:
4390 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004391 case Match_RequiresV6:
4392 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4393 case Match_RequiresThumb2:
4394 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004395 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004396
Eric Christopherc223e2b2010-10-29 09:26:59 +00004397 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004398 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004399}
4400
Jim Grosbach1355cf12011-07-26 17:10:22 +00004401/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004402bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4403 StringRef IDVal = DirectiveID.getIdentifier();
4404 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004405 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004406 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004407 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004408 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004409 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004410 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004411 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004412 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004413 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004414 return true;
4415}
4416
Jim Grosbach1355cf12011-07-26 17:10:22 +00004417/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004418/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004419bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4421 for (;;) {
4422 const MCExpr *Value;
4423 if (getParser().ParseExpression(Value))
4424 return true;
4425
Chris Lattneraaec2052010-01-19 19:46:13 +00004426 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004427
4428 if (getLexer().is(AsmToken::EndOfStatement))
4429 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004430
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004431 // FIXME: Improve diagnostic.
4432 if (getLexer().isNot(AsmToken::Comma))
4433 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004434 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004435 }
4436 }
4437
Sean Callananb9a25b72010-01-19 20:27:46 +00004438 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004439 return false;
4440}
4441
Jim Grosbach1355cf12011-07-26 17:10:22 +00004442/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004443/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004444bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004445 if (getLexer().isNot(AsmToken::EndOfStatement))
4446 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004447 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004448
4449 // TODO: set thumb mode
4450 // TODO: tell the MC streamer the mode
4451 // getParser().getStreamer().Emit???();
4452 return false;
4453}
4454
Jim Grosbach1355cf12011-07-26 17:10:22 +00004455/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004456/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004457bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004458 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4459 bool isMachO = MAI.hasSubsectionsViaSymbols();
4460 StringRef Name;
4461
4462 // Darwin asm has function name after .thumb_func direction
4463 // ELF doesn't
4464 if (isMachO) {
4465 const AsmToken &Tok = Parser.getTok();
4466 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4467 return Error(L, "unexpected token in .thumb_func directive");
4468 Name = Tok.getString();
4469 Parser.Lex(); // Consume the identifier token.
4470 }
4471
Kevin Enderby515d5092009-10-15 20:48:48 +00004472 if (getLexer().isNot(AsmToken::EndOfStatement))
4473 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004474 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004475
Rafael Espindola64695402011-05-16 16:17:21 +00004476 // FIXME: assuming function name will be the line following .thumb_func
4477 if (!isMachO) {
4478 Name = Parser.getTok().getString();
4479 }
4480
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004481 // Mark symbol as a thumb symbol.
4482 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4483 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004484 return false;
4485}
4486
Jim Grosbach1355cf12011-07-26 17:10:22 +00004487/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004488/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004489bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004490 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004491 if (Tok.isNot(AsmToken::Identifier))
4492 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004493 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004494 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004495 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004496 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004497 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004498 else
4499 return Error(L, "unrecognized syntax mode in .syntax directive");
4500
4501 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004502 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004503 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004504
4505 // TODO tell the MC streamer the mode
4506 // getParser().getStreamer().Emit???();
4507 return false;
4508}
4509
Jim Grosbach1355cf12011-07-26 17:10:22 +00004510/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004511/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004512bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004513 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004514 if (Tok.isNot(AsmToken::Integer))
4515 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004516 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004517 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004518 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004519 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004520 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004521 else
4522 return Error(L, "invalid operand to .code directive");
4523
4524 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004525 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004526 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004527
Evan Cheng32869202011-07-08 22:36:29 +00004528 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004529 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004530 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004531 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004532 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004533 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004534 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004535 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004536 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004537
Kevin Enderby515d5092009-10-15 20:48:48 +00004538 return false;
4539}
4540
Sean Callanan90b70972010-04-07 20:29:34 +00004541extern "C" void LLVMInitializeARMAsmLexer();
4542
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004543/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004544extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004545 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4546 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004547 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004548}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004549
Chris Lattner0692ee62010-09-06 19:11:01 +00004550#define GET_REGISTER_MATCHER
4551#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004552#include "ARMGenAsmMatcher.inc"