blob: 11b6574c2866bd2fe26165784b363c540fd02c66 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Owen Anderson0c9f2502011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000036
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattner3a697562010-10-28 17:20:03 +000039namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000042
Evan Cheng94b95502011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000047 struct {
48 ARMCC::CondCodes Cond; // Condition for IT block.
49 unsigned Mask:4; // Condition mask for instructions.
50 // Starting at first 1 (from lsb).
51 // '1' condition as indicated in IT.
52 // '0' inverse of condition (else).
53 // Count of instructions in IT block is
54 // 4 - trailingzeroes(mask)
55
56 bool FirstCond; // Explicit flag for when we're parsing the
57 // First instruction in the IT block. It's
58 // implied in the mask, so needs special
59 // handling.
60
61 unsigned CurPosition; // Current position in parsing of IT
62 // block. In range [0,3]. Initialized
63 // according to count of instructions in block.
64 // ~0U if no active IT block.
65 } ITState;
66 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000067 void forwardITPosition() {
68 if (!inITBlock()) return;
69 // Move to the next instruction in the IT block, if there is one. If not,
70 // mark the block as done.
71 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
72 if (++ITState.CurPosition == 5 - TZ)
73 ITState.CurPosition = ~0U; // Done with the IT block after this.
74 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000075
76
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000078 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
79
80 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbach1355cf12011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseDirectiveWord(unsigned Size, SMLoc L);
93 bool parseDirectiveThumb(SMLoc L);
94 bool parseDirectiveThumbFunc(SMLoc L);
95 bool parseDirectiveCode(SMLoc L);
96 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000097
Jim Grosbach1355cf12011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000103
Evan Chengebdeeab2011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloyacad68d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng32869202011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000123 }
James Molloyacad68d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000127
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000130
Chris Lattner0692ee62010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach89df9962011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000141 OperandMatchResultTy parseCoprocOptionOperand(
142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000143 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000149 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
150 StringRef Op, int Low, int High);
151 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
152 return parsePKHImm(O, "lsl", 0, 31);
153 }
154 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
155 return parsePKHImm(O, "asr", 1, 32);
156 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000157 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000158 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000159 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000160 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000161 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000162 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000163 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000164
165 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000166 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
168 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000170 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000172 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000174 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000176 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000178 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000180 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000182 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000184 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000192 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000194 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000196 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000198 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000200
201 bool validateInstruction(MCInst &Inst,
202 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000203 void processInstruction(MCInst &Inst,
204 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000205 bool shouldOmitCCOutOperand(StringRef Mnemonic,
206 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000207
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000208public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000209 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000210 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000211 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000212 Match_RequiresV6,
213 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000214 };
215
Evan Chengffc0e732011-07-09 05:47:46 +0000216 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000217 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000218 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000219
Evan Chengebdeeab2011-07-08 01:53:10 +0000220 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000221 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000222
223 // Not in an ITBlock to start with.
224 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000225 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000226
Jim Grosbach1355cf12011-07-26 17:10:22 +0000227 // Implementation of the MCTargetAsmParser interface:
228 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
229 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000230 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000231 bool ParseDirective(AsmToken DirectiveID);
232
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 unsigned checkTargetMatchPredicate(MCInst &Inst);
234
Jim Grosbach1355cf12011-07-26 17:10:22 +0000235 bool MatchAndEmitInstruction(SMLoc IDLoc,
236 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
237 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000238};
Jim Grosbach16c74252010-10-29 14:46:02 +0000239} // end anonymous namespace
240
Chris Lattner3a697562010-10-28 17:20:03 +0000241namespace {
242
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000243/// ARMOperand - Instances of this class represent a parsed ARM machine
244/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000245class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000246 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000247 k_CondCode,
248 k_CCOut,
249 k_ITCondMask,
250 k_CoprocNum,
251 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000252 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000253 k_Immediate,
254 k_FPImmediate,
255 k_MemBarrierOpt,
256 k_Memory,
257 k_PostIndexRegister,
258 k_MSRMask,
259 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000260 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000261 k_Register,
262 k_RegisterList,
263 k_DPRRegisterList,
264 k_SPRRegisterList,
265 k_ShiftedRegister,
266 k_ShiftedImmediate,
267 k_ShifterImmediate,
268 k_RotateImmediate,
269 k_BitfieldDescriptor,
270 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000271 } Kind;
272
Sean Callanan76264762010-04-02 22:27:05 +0000273 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000274 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000275
276 union {
277 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000278 ARMCC::CondCodes Val;
279 } CC;
280
281 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000282 unsigned Val;
283 } Cop;
284
285 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000286 unsigned Val;
287 } CoprocOption;
288
289 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000290 unsigned Mask:4;
291 } ITMask;
292
293 struct {
294 ARM_MB::MemBOpt Val;
295 } MBOpt;
296
297 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000298 ARM_PROC::IFlags Val;
299 } IFlags;
300
301 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000302 unsigned Val;
303 } MMask;
304
305 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000306 const char *Data;
307 unsigned Length;
308 } Tok;
309
310 struct {
311 unsigned RegNum;
312 } Reg;
313
Bill Wendling8155e5b2010-11-06 22:19:43 +0000314 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000315 unsigned Val;
316 } VectorIndex;
317
318 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000319 const MCExpr *Val;
320 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000321
Jim Grosbach9d390362011-10-03 23:38:36 +0000322 struct {
323 unsigned Val; // encoded 8-bit representation
324 } FPImm;
325
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000326 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000327 struct {
328 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000329 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
330 // was specified.
331 const MCConstantExpr *OffsetImm; // Offset immediate value
332 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
333 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000334 unsigned ShiftImm; // shift for OffsetReg.
335 unsigned Alignment; // 0 = no alignment specified
336 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000337 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000338 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000339
340 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000341 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000342 bool isAdd;
343 ARM_AM::ShiftOpc ShiftTy;
344 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000345 } PostIdxReg;
346
347 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000348 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000349 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000350 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000351 struct {
352 ARM_AM::ShiftOpc ShiftTy;
353 unsigned SrcReg;
354 unsigned ShiftReg;
355 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000356 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000357 struct {
358 ARM_AM::ShiftOpc ShiftTy;
359 unsigned SrcReg;
360 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000361 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000362 struct {
363 unsigned Imm;
364 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000365 struct {
366 unsigned LSB;
367 unsigned Width;
368 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000369 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000370
Bill Wendling146018f2010-11-06 21:42:12 +0000371 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
372public:
Sean Callanan76264762010-04-02 22:27:05 +0000373 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
374 Kind = o.Kind;
375 StartLoc = o.StartLoc;
376 EndLoc = o.EndLoc;
377 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000378 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000379 CC = o.CC;
380 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000381 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000382 ITMask = o.ITMask;
383 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000384 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000385 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000386 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000387 case k_CCOut:
388 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000389 Reg = o.Reg;
390 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000391 case k_RegisterList:
392 case k_DPRRegisterList:
393 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000394 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_CoprocNum:
397 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000398 Cop = o.Cop;
399 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000400 case k_CoprocOption:
401 CoprocOption = o.CoprocOption;
402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000404 Imm = o.Imm;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000407 FPImm = o.FPImm;
408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000410 MBOpt = o.MBOpt;
411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000412 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000413 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000414 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000415 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000416 PostIdxReg = o.PostIdxReg;
417 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000418 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000419 MMask = o.MMask;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000422 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000423 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000424 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000425 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000426 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000427 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000428 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000431 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000434 RotImm = o.RotImm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000437 Bitfield = o.Bitfield;
438 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000439 case k_VectorIndex:
440 VectorIndex = o.VectorIndex;
441 break;
Sean Callanan76264762010-04-02 22:27:05 +0000442 }
443 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000444
Sean Callanan76264762010-04-02 22:27:05 +0000445 /// getStartLoc - Get the location of the first token of this operand.
446 SMLoc getStartLoc() const { return StartLoc; }
447 /// getEndLoc - Get the location of the last token of this operand.
448 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000449
Daniel Dunbar8462b302010-08-11 06:36:53 +0000450 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000452 return CC.Val;
453 }
454
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000455 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000457 return Cop.Val;
458 }
459
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000460 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000462 return StringRef(Tok.Data, Tok.Length);
463 }
464
465 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000466 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000467 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000468 }
469
Bill Wendling5fa22a12010-11-09 23:28:44 +0000470 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
472 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000473 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000474 }
475
Kevin Enderbycfe07242009-10-13 22:19:02 +0000476 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000477 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000478 return Imm.Val;
479 }
480
Jim Grosbach9d390362011-10-03 23:38:36 +0000481 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000483 return FPImm.Val;
484 }
485
Jim Grosbach460a9052011-10-07 23:56:00 +0000486 unsigned getVectorIndex() const {
487 assert(Kind == k_VectorIndex && "Invalid access!");
488 return VectorIndex.Val;
489 }
490
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000491 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000493 return MBOpt.Val;
494 }
495
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000496 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000497 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000498 return IFlags.Val;
499 }
500
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000501 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000502 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000503 return MMask.Val;
504 }
505
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000506 bool isCoprocNum() const { return Kind == k_CoprocNum; }
507 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000508 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000509 bool isCondCode() const { return Kind == k_CondCode; }
510 bool isCCOut() const { return Kind == k_CCOut; }
511 bool isITMask() const { return Kind == k_ITCondMask; }
512 bool isITCondCode() const { return Kind == k_CondCode; }
513 bool isImm() const { return Kind == k_Immediate; }
514 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000515 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000516 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000517 return false;
518 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
519 if (!CE) return false;
520 int64_t Value = CE->getValue();
521 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
522 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000523 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000525 return false;
526 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
527 if (!CE) return false;
528 int64_t Value = CE->getValue();
529 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
530 }
531 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000533 return false;
534 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
535 if (!CE) return false;
536 int64_t Value = CE->getValue();
537 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
538 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000539 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000540 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000541 return false;
542 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
543 if (!CE) return false;
544 int64_t Value = CE->getValue();
545 return Value >= 0 && Value < 256;
546 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000547 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000548 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000549 return false;
550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
551 if (!CE) return false;
552 int64_t Value = CE->getValue();
553 return Value >= 0 && Value < 8;
554 }
555 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000556 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000557 return false;
558 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
559 if (!CE) return false;
560 int64_t Value = CE->getValue();
561 return Value >= 0 && Value < 16;
562 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000563 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000564 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000565 return false;
566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return Value >= 0 && Value < 32;
570 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000571 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000572 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000573 return false;
574 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
575 if (!CE) return false;
576 int64_t Value = CE->getValue();
577 return Value > 0 && Value < 17;
578 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000579 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000580 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000581 return false;
582 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
583 if (!CE) return false;
584 int64_t Value = CE->getValue();
585 return Value > 0 && Value < 33;
586 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000587 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000588 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000589 return false;
590 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
591 if (!CE) return false;
592 int64_t Value = CE->getValue();
593 return Value >= 0 && Value < 65536;
594 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000595 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000596 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000597 return false;
598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
599 // If it's not a constant expression, it'll generate a fixup and be
600 // handled later.
601 if (!CE) return true;
602 int64_t Value = CE->getValue();
603 return Value >= 0 && Value < 65536;
604 }
Jim Grosbached838482011-07-26 16:24:27 +0000605 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000606 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000607 return false;
608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value <= 0xffffff;
612 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000613 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 if (!CE) return false;
618 int64_t Value = CE->getValue();
619 return Value > 0 && Value < 33;
620 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000621 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 if (!CE) return false;
626 int64_t Value = CE->getValue();
627 return Value >= 0 && Value < 32;
628 }
629 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000630 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000631 return false;
632 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
633 if (!CE) return false;
634 int64_t Value = CE->getValue();
635 return Value > 0 && Value <= 32;
636 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000637 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000638 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000639 return false;
640 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
641 if (!CE) return false;
642 int64_t Value = CE->getValue();
643 return ARM_AM::getSOImmVal(Value) != -1;
644 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000645 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000646 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000647 return false;
648 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
649 if (!CE) return false;
650 int64_t Value = CE->getValue();
651 return ARM_AM::getT2SOImmVal(Value) != -1;
652 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000653 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000654 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000655 return false;
656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
657 if (!CE) return false;
658 int64_t Value = CE->getValue();
659 return Value == 1 || Value == 0;
660 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000661 bool isReg() const { return Kind == k_Register; }
662 bool isRegList() const { return Kind == k_RegisterList; }
663 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
664 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
665 bool isToken() const { return Kind == k_Token; }
666 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
667 bool isMemory() const { return Kind == k_Memory; }
668 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
669 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
670 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
671 bool isRotImm() const { return Kind == k_RotateImmediate; }
672 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
673 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000674 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000675 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000676 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000677 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000678 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000679 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000680 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000681 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
682 (alignOK || Memory.Alignment == 0);
683 }
684 bool isAlignedMemory() const {
685 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000686 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000687 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000688 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000689 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000690 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000691 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000692 if (!Memory.OffsetImm) return true;
693 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000694 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000695 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000696 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000697 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000698 return false;
699 // Immediate offset in range [-4095, 4095].
700 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
701 if (!CE) return false;
702 int64_t Val = CE->getValue();
703 return Val > -4096 && Val < 4096;
704 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000705 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000706 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000707 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000708 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000709 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000710 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000711 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000712 if (!Memory.OffsetImm) return true;
713 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000714 return Val > -256 && Val < 256;
715 }
716 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000717 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000718 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000719 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000720 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
721 // Immediate offset in range [-255, 255].
722 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
723 if (!CE) return false;
724 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000725 // Special case, #-0 is INT32_MIN.
726 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000727 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000728 bool isAddrMode5() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000729 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000730 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000731 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000732 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000733 if (!Memory.OffsetImm) return true;
734 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000735 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
736 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000737 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000738 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000739 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000740 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000741 return false;
742 return true;
743 }
744 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000745 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000746 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
747 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000748 return false;
749 return true;
750 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000751 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000752 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000753 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000754 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000755 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000756 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000757 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
758 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000759 return false;
760 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000761 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000762 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000763 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000764 return false;
765 return true;
766 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000767 bool isMemThumbRR() const {
768 // Thumb reg+reg addressing is simple. Just two registers, a base and
769 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000770 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000771 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000772 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000773 return isARMLowRegister(Memory.BaseRegNum) &&
774 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000775 }
776 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000777 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000778 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000779 return false;
780 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000781 if (!Memory.OffsetImm) return true;
782 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000783 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
784 }
Jim Grosbach38466302011-08-19 18:55:51 +0000785 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000786 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000787 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000788 return false;
789 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000790 if (!Memory.OffsetImm) return true;
791 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000792 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
793 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000794 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000795 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000796 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000797 return false;
798 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000799 if (!Memory.OffsetImm) return true;
800 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000801 return Val >= 0 && Val <= 31;
802 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000803 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000804 if (!isMemory() || Memory.OffsetRegNum != 0 ||
805 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000806 return false;
807 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000808 if (!Memory.OffsetImm) return true;
809 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000810 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000811 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000812 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000813 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000814 return false;
815 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000816 if (!Memory.OffsetImm) return true;
817 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000818 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
819 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000820 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000821 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000822 return false;
823 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000824 if (!Memory.OffsetImm) return true;
825 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000826 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
827 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000828 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000829 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000830 return false;
831 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000832 if (!Memory.OffsetImm) return true;
833 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000834 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000835 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000836 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000837 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000838 return false;
839 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000840 if (!Memory.OffsetImm) return true;
841 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000842 return Val >= 0 && Val < 256;
843 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000844 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000845 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000846 return false;
847 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000848 if (!Memory.OffsetImm) return true;
849 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000850 return Val > -256 && Val < 0;
851 }
852 bool isMemUImm12Offset() const {
853 // If we have an immediate that's not a constant, treat it as a label
854 // reference needing a fixup. If it is a constant, it's something else
855 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000856 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000857 return true;
858
Jim Grosbach57dcb852011-10-11 17:29:55 +0000859 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000860 return false;
861 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000862 if (!Memory.OffsetImm) return true;
863 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000864 return (Val >= 0 && Val < 4096);
865 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000866 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000867 // If we have an immediate that's not a constant, treat it as a label
868 // reference needing a fixup. If it is a constant, it's something else
869 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000870 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000871 return true;
872
Jim Grosbach57dcb852011-10-11 17:29:55 +0000873 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000874 return false;
875 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000876 if (!Memory.OffsetImm) return true;
877 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000878 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000879 }
880 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000881 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000882 return false;
883 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
884 if (!CE) return false;
885 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000886 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000887 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000888 bool isPostIdxImm8s4() const {
889 if (Kind != k_Immediate)
890 return false;
891 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
892 if (!CE) return false;
893 int64_t Val = CE->getValue();
894 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
895 (Val == INT32_MIN);
896 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000897
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000898 bool isMSRMask() const { return Kind == k_MSRMask; }
899 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000900
Jim Grosbach0e387b22011-10-17 22:26:03 +0000901 // NEON operands.
Jim Grosbach460a9052011-10-07 23:56:00 +0000902 bool isVectorIndex8() const {
903 if (Kind != k_VectorIndex) return false;
904 return VectorIndex.Val < 8;
905 }
906 bool isVectorIndex16() const {
907 if (Kind != k_VectorIndex) return false;
908 return VectorIndex.Val < 4;
909 }
910 bool isVectorIndex32() const {
911 if (Kind != k_VectorIndex) return false;
912 return VectorIndex.Val < 2;
913 }
914
Jim Grosbach0e387b22011-10-17 22:26:03 +0000915 bool isNEONi8splat() const {
916 if (Kind != k_Immediate)
917 return false;
918 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
919 // Must be a constant.
920 if (!CE) return false;
921 int64_t Value = CE->getValue();
922 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
923 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000924 return Value >= 0 && Value < 256;
925 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000926
Jim Grosbachea461102011-10-17 23:09:09 +0000927 bool isNEONi16splat() const {
928 if (Kind != k_Immediate)
929 return false;
930 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
931 // Must be a constant.
932 if (!CE) return false;
933 int64_t Value = CE->getValue();
934 // i16 value in the range [0,255] or [0x0100, 0xff00]
935 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
936 }
937
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000938 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +0000939 // Add as immediates when possible. Null MCExpr = 0.
940 if (Expr == 0)
941 Inst.addOperand(MCOperand::CreateImm(0));
942 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000943 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
944 else
945 Inst.addOperand(MCOperand::CreateExpr(Expr));
946 }
947
Daniel Dunbar8462b302010-08-11 06:36:53 +0000948 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000949 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000950 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +0000951 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
952 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000953 }
954
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000955 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
956 assert(N == 1 && "Invalid number of operands!");
957 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
958 }
959
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000960 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
961 assert(N == 1 && "Invalid number of operands!");
962 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
963 }
964
965 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
966 assert(N == 1 && "Invalid number of operands!");
967 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
968 }
969
Jim Grosbach89df9962011-08-26 21:43:41 +0000970 void addITMaskOperands(MCInst &Inst, unsigned N) const {
971 assert(N == 1 && "Invalid number of operands!");
972 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
973 }
974
975 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
976 assert(N == 1 && "Invalid number of operands!");
977 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
978 }
979
Jim Grosbachd67641b2010-12-06 18:21:12 +0000980 void addCCOutOperands(MCInst &Inst, unsigned N) const {
981 assert(N == 1 && "Invalid number of operands!");
982 Inst.addOperand(MCOperand::CreateReg(getReg()));
983 }
984
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000985 void addRegOperands(MCInst &Inst, unsigned N) const {
986 assert(N == 1 && "Invalid number of operands!");
987 Inst.addOperand(MCOperand::CreateReg(getReg()));
988 }
989
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000990 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +0000991 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000992 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
993 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
994 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000995 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000996 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000997 }
998
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000999 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001000 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001001 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1002 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001003 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001004 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001005 }
1006
Jim Grosbach580f4a92011-07-25 22:20:28 +00001007 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001008 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001009 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1010 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001011 }
1012
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001013 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001014 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001015 const SmallVectorImpl<unsigned> &RegList = getRegList();
1016 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001017 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1018 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001019 }
1020
Bill Wendling0f630752010-11-17 04:32:08 +00001021 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1022 addRegListOperands(Inst, N);
1023 }
1024
1025 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1026 addRegListOperands(Inst, N);
1027 }
1028
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001029 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1030 assert(N == 1 && "Invalid number of operands!");
1031 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1032 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1033 }
1034
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001035 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1036 assert(N == 1 && "Invalid number of operands!");
1037 // Munge the lsb/width into a bitfield mask.
1038 unsigned lsb = Bitfield.LSB;
1039 unsigned width = Bitfield.Width;
1040 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1041 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1042 (32 - (lsb + width)));
1043 Inst.addOperand(MCOperand::CreateImm(Mask));
1044 }
1045
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001046 void addImmOperands(MCInst &Inst, unsigned N) const {
1047 assert(N == 1 && "Invalid number of operands!");
1048 addExpr(Inst, getImm());
1049 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001050
Jim Grosbach9d390362011-10-03 23:38:36 +00001051 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1052 assert(N == 1 && "Invalid number of operands!");
1053 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1054 }
1055
Jim Grosbacha77295d2011-09-08 22:07:06 +00001056 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1057 assert(N == 1 && "Invalid number of operands!");
1058 // FIXME: We really want to scale the value here, but the LDRD/STRD
1059 // instruction don't encode operands that way yet.
1060 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1061 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1062 }
1063
Jim Grosbach72f39f82011-08-24 21:22:15 +00001064 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1065 assert(N == 1 && "Invalid number of operands!");
1066 // The immediate is scaled by four in the encoding and is stored
1067 // in the MCInst as such. Lop off the low two bits here.
1068 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1069 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1070 }
1071
1072 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
1074 // The immediate is scaled by four in the encoding and is stored
1075 // in the MCInst as such. Lop off the low two bits here.
1076 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1077 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1078 }
1079
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001080 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!");
1082 addExpr(Inst, getImm());
1083 }
1084
Jim Grosbach83ab0702011-07-13 22:01:08 +00001085 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1086 assert(N == 1 && "Invalid number of operands!");
1087 addExpr(Inst, getImm());
1088 }
1089
1090 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1091 assert(N == 1 && "Invalid number of operands!");
1092 addExpr(Inst, getImm());
1093 }
1094
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001095 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1096 assert(N == 1 && "Invalid number of operands!");
1097 addExpr(Inst, getImm());
1098 }
1099
Jim Grosbachf4943352011-07-25 23:09:14 +00001100 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1101 assert(N == 1 && "Invalid number of operands!");
1102 // The constant encodes as the immediate-1, and we store in the instruction
1103 // the bits as encoded, so subtract off one here.
1104 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1105 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1106 }
1107
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001108 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1109 assert(N == 1 && "Invalid number of operands!");
1110 // The constant encodes as the immediate-1, and we store in the instruction
1111 // the bits as encoded, so subtract off one here.
1112 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1113 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1114 }
1115
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001116 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!");
1118 addExpr(Inst, getImm());
1119 }
1120
Jim Grosbachffa32252011-07-19 19:13:28 +00001121 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
1123 addExpr(Inst, getImm());
1124 }
1125
Jim Grosbached838482011-07-26 16:24:27 +00001126 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1127 assert(N == 1 && "Invalid number of operands!");
1128 addExpr(Inst, getImm());
1129 }
1130
Jim Grosbach70939ee2011-08-17 21:51:27 +00001131 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1132 assert(N == 1 && "Invalid number of operands!");
1133 // The constant encodes as the immediate, except for 32, which encodes as
1134 // zero.
1135 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1136 unsigned Imm = CE->getValue();
1137 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1138 }
1139
Jim Grosbachf6c05252011-07-21 17:23:04 +00001140 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1141 assert(N == 1 && "Invalid number of operands!");
1142 addExpr(Inst, getImm());
1143 }
1144
1145 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1146 assert(N == 1 && "Invalid number of operands!");
1147 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1148 // the instruction as well.
1149 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1150 int Val = CE->getValue();
1151 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1152 }
1153
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001154 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1155 assert(N == 1 && "Invalid number of operands!");
1156 addExpr(Inst, getImm());
1157 }
1158
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001159 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1160 assert(N == 1 && "Invalid number of operands!");
1161 addExpr(Inst, getImm());
1162 }
1163
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001164 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
1166 addExpr(Inst, getImm());
1167 }
1168
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001169 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1170 assert(N == 1 && "Invalid number of operands!");
1171 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1172 }
1173
Jim Grosbach7ce05792011-08-03 23:50:40 +00001174 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1175 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001176 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001177 }
1178
Jim Grosbach57dcb852011-10-11 17:29:55 +00001179 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 2 && "Invalid number of operands!");
1181 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1182 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1183 }
1184
Jim Grosbach7ce05792011-08-03 23:50:40 +00001185 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1186 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001187 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1188 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001189 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1190 // Special case for #-0
1191 if (Val == INT32_MIN) Val = 0;
1192 if (Val < 0) Val = -Val;
1193 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1194 } else {
1195 // For register offset, we encode the shift type and negation flag
1196 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001197 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1198 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001199 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001200 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1201 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001202 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001203 }
1204
Jim Grosbach039c2e12011-08-04 23:01:30 +00001205 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1206 assert(N == 2 && "Invalid number of operands!");
1207 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1208 assert(CE && "non-constant AM2OffsetImm operand!");
1209 int32_t Val = CE->getValue();
1210 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1211 // Special case for #-0
1212 if (Val == INT32_MIN) Val = 0;
1213 if (Val < 0) Val = -Val;
1214 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1215 Inst.addOperand(MCOperand::CreateReg(0));
1216 Inst.addOperand(MCOperand::CreateImm(Val));
1217 }
1218
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001219 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1220 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001221 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1222 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001223 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1224 // Special case for #-0
1225 if (Val == INT32_MIN) Val = 0;
1226 if (Val < 0) Val = -Val;
1227 Val = ARM_AM::getAM3Opc(AddSub, Val);
1228 } else {
1229 // For register offset, we encode the shift type and negation flag
1230 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001231 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001232 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001233 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1234 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001235 Inst.addOperand(MCOperand::CreateImm(Val));
1236 }
1237
1238 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1239 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001240 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001241 int32_t Val =
1242 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1243 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1244 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001245 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001246 }
1247
1248 // Constant offset.
1249 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1250 int32_t Val = CE->getValue();
1251 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1252 // Special case for #-0
1253 if (Val == INT32_MIN) Val = 0;
1254 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001255 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001256 Inst.addOperand(MCOperand::CreateReg(0));
1257 Inst.addOperand(MCOperand::CreateImm(Val));
1258 }
1259
Jim Grosbach7ce05792011-08-03 23:50:40 +00001260 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 2 && "Invalid number of operands!");
1262 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001263 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001264 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1265 // Special case for #-0
1266 if (Val == INT32_MIN) Val = 0;
1267 if (Val < 0) Val = -Val;
1268 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001269 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001270 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001271 }
1272
Jim Grosbacha77295d2011-09-08 22:07:06 +00001273 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1274 assert(N == 2 && "Invalid number of operands!");
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 Grosbacha77295d2011-09-08 22:07:06 +00001277 Inst.addOperand(MCOperand::CreateImm(Val));
1278 }
1279
Jim Grosbachb6aed502011-09-09 18:37:27 +00001280 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 2 && "Invalid number of operands!");
1282 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001283 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1284 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001285 Inst.addOperand(MCOperand::CreateImm(Val));
1286 }
1287
Jim Grosbach7ce05792011-08-03 23:50:40 +00001288 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1289 assert(N == 2 && "Invalid number of operands!");
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));
Chris Lattner14b93852010-10-29 00:27:31 +00001293 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001294
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001295 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1296 addMemImm8OffsetOperands(Inst, N);
1297 }
1298
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001299 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001300 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001301 }
1302
1303 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1304 assert(N == 2 && "Invalid number of operands!");
1305 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001306 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001307 addExpr(Inst, getImm());
1308 Inst.addOperand(MCOperand::CreateImm(0));
1309 return;
1310 }
1311
1312 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001313 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1314 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001315 Inst.addOperand(MCOperand::CreateImm(Val));
1316 }
1317
Jim Grosbach7ce05792011-08-03 23:50:40 +00001318 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1319 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001320 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001321 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001322 addExpr(Inst, getImm());
1323 Inst.addOperand(MCOperand::CreateImm(0));
1324 return;
1325 }
1326
1327 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001328 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1329 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001330 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001331 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001332
Jim Grosbach7f739be2011-09-19 22:21:13 +00001333 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1334 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001335 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1336 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001337 }
1338
1339 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1340 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001341 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1342 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001343 }
1344
Jim Grosbach7ce05792011-08-03 23:50:40 +00001345 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1346 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001347 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1348 Memory.ShiftImm, Memory.ShiftType);
1349 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1350 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001351 Inst.addOperand(MCOperand::CreateImm(Val));
1352 }
1353
Jim Grosbachab899c12011-09-07 23:10:15 +00001354 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1355 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001356 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1357 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1358 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001359 }
1360
Jim Grosbach7ce05792011-08-03 23:50:40 +00001361 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1362 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001363 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1364 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001365 }
1366
Jim Grosbach60f91a32011-08-19 17:55:24 +00001367 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1368 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001369 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1370 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001371 Inst.addOperand(MCOperand::CreateImm(Val));
1372 }
1373
Jim Grosbach38466302011-08-19 18:55:51 +00001374 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1375 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001376 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1377 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001378 Inst.addOperand(MCOperand::CreateImm(Val));
1379 }
1380
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001381 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1382 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001383 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1384 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001385 Inst.addOperand(MCOperand::CreateImm(Val));
1386 }
1387
Jim Grosbachecd85892011-08-19 18:13:48 +00001388 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001390 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1391 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001392 Inst.addOperand(MCOperand::CreateImm(Val));
1393 }
1394
Jim Grosbach7ce05792011-08-03 23:50:40 +00001395 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1396 assert(N == 1 && "Invalid number of operands!");
1397 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1398 assert(CE && "non-constant post-idx-imm8 operand!");
1399 int Imm = CE->getValue();
1400 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001401 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001402 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1403 Inst.addOperand(MCOperand::CreateImm(Imm));
1404 }
1405
Jim Grosbach2bd01182011-10-11 21:55:36 +00001406 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
1408 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1409 assert(CE && "non-constant post-idx-imm8s4 operand!");
1410 int Imm = CE->getValue();
1411 bool isAdd = Imm >= 0;
1412 if (Imm == INT32_MIN) Imm = 0;
1413 // Immediate is scaled by 4.
1414 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1415 Inst.addOperand(MCOperand::CreateImm(Imm));
1416 }
1417
Jim Grosbach7ce05792011-08-03 23:50:40 +00001418 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1419 assert(N == 2 && "Invalid number of operands!");
1420 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001421 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1422 }
1423
1424 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 2 && "Invalid number of operands!");
1426 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1427 // The sign, shift type, and shift amount are encoded in a single operand
1428 // using the AM2 encoding helpers.
1429 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1430 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1431 PostIdxReg.ShiftTy);
1432 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001433 }
1434
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001435 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1436 assert(N == 1 && "Invalid number of operands!");
1437 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1438 }
1439
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001440 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1441 assert(N == 1 && "Invalid number of operands!");
1442 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1443 }
1444
Jim Grosbach460a9052011-10-07 23:56:00 +00001445 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1446 assert(N == 1 && "Invalid number of operands!");
1447 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1448 }
1449
1450 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1451 assert(N == 1 && "Invalid number of operands!");
1452 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1453 }
1454
1455 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
1457 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1458 }
1459
Jim Grosbach0e387b22011-10-17 22:26:03 +00001460 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462 // The immediate encodes the type of constant as well as the value.
1463 // Mask in that this is an i8 splat.
1464 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1465 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1466 }
1467
Jim Grosbachea461102011-10-17 23:09:09 +00001468 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1469 assert(N == 1 && "Invalid number of operands!");
1470 // The immediate encodes the type of constant as well as the value.
1471 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1472 unsigned Value = CE->getValue();
1473 if (Value >= 256)
1474 Value = (Value >> 8) | 0xa00;
1475 else
1476 Value |= 0x800;
1477 Inst.addOperand(MCOperand::CreateImm(Value));
1478 }
1479
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001480 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001481
Jim Grosbach89df9962011-08-26 21:43:41 +00001482 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001483 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001484 Op->ITMask.Mask = Mask;
1485 Op->StartLoc = S;
1486 Op->EndLoc = S;
1487 return Op;
1488 }
1489
Chris Lattner3a697562010-10-28 17:20:03 +00001490 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001491 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001492 Op->CC.Val = CC;
1493 Op->StartLoc = S;
1494 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001495 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001496 }
1497
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001498 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001499 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001500 Op->Cop.Val = CopVal;
1501 Op->StartLoc = S;
1502 Op->EndLoc = S;
1503 return Op;
1504 }
1505
1506 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001507 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001508 Op->Cop.Val = CopVal;
1509 Op->StartLoc = S;
1510 Op->EndLoc = S;
1511 return Op;
1512 }
1513
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001514 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1515 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1516 Op->Cop.Val = Val;
1517 Op->StartLoc = S;
1518 Op->EndLoc = E;
1519 return Op;
1520 }
1521
Jim Grosbachd67641b2010-12-06 18:21:12 +00001522 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001523 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001524 Op->Reg.RegNum = RegNum;
1525 Op->StartLoc = S;
1526 Op->EndLoc = S;
1527 return Op;
1528 }
1529
Chris Lattner3a697562010-10-28 17:20:03 +00001530 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001531 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001532 Op->Tok.Data = Str.data();
1533 Op->Tok.Length = Str.size();
1534 Op->StartLoc = S;
1535 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001536 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001537 }
1538
Bill Wendling50d0f582010-11-18 23:43:05 +00001539 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001540 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001541 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001542 Op->StartLoc = S;
1543 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001544 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001545 }
1546
Jim Grosbache8606dc2011-07-13 17:50:29 +00001547 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1548 unsigned SrcReg,
1549 unsigned ShiftReg,
1550 unsigned ShiftImm,
1551 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001552 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001553 Op->RegShiftedReg.ShiftTy = ShTy;
1554 Op->RegShiftedReg.SrcReg = SrcReg;
1555 Op->RegShiftedReg.ShiftReg = ShiftReg;
1556 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001557 Op->StartLoc = S;
1558 Op->EndLoc = E;
1559 return Op;
1560 }
1561
Owen Anderson92a20222011-07-21 18:54:16 +00001562 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1563 unsigned SrcReg,
1564 unsigned ShiftImm,
1565 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001566 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001567 Op->RegShiftedImm.ShiftTy = ShTy;
1568 Op->RegShiftedImm.SrcReg = SrcReg;
1569 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001570 Op->StartLoc = S;
1571 Op->EndLoc = E;
1572 return Op;
1573 }
1574
Jim Grosbach580f4a92011-07-25 22:20:28 +00001575 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001576 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001577 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001578 Op->ShifterImm.isASR = isASR;
1579 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001580 Op->StartLoc = S;
1581 Op->EndLoc = E;
1582 return Op;
1583 }
1584
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001585 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001586 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001587 Op->RotImm.Imm = Imm;
1588 Op->StartLoc = S;
1589 Op->EndLoc = E;
1590 return Op;
1591 }
1592
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001593 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1594 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001595 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001596 Op->Bitfield.LSB = LSB;
1597 Op->Bitfield.Width = Width;
1598 Op->StartLoc = S;
1599 Op->EndLoc = E;
1600 return Op;
1601 }
1602
Bill Wendling7729e062010-11-09 22:44:22 +00001603 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001604 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001605 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001606 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001607
Jim Grosbachd300b942011-09-13 22:56:44 +00001608 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001609 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001610 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001611 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001612 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001613
1614 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001615 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001616 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001617 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001618 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001619 Op->StartLoc = StartLoc;
1620 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001621 return Op;
1622 }
1623
Jim Grosbach460a9052011-10-07 23:56:00 +00001624 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1625 MCContext &Ctx) {
1626 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1627 Op->VectorIndex.Val = Idx;
1628 Op->StartLoc = S;
1629 Op->EndLoc = E;
1630 return Op;
1631 }
1632
Chris Lattner3a697562010-10-28 17:20:03 +00001633 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001634 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001635 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001636 Op->StartLoc = S;
1637 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001638 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001639 }
1640
Jim Grosbach9d390362011-10-03 23:38:36 +00001641 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001642 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001643 Op->FPImm.Val = Val;
1644 Op->StartLoc = S;
1645 Op->EndLoc = S;
1646 return Op;
1647 }
1648
Jim Grosbach7ce05792011-08-03 23:50:40 +00001649 static ARMOperand *CreateMem(unsigned BaseRegNum,
1650 const MCConstantExpr *OffsetImm,
1651 unsigned OffsetRegNum,
1652 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001653 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001654 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001655 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001656 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001657 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001658 Op->Memory.BaseRegNum = BaseRegNum;
1659 Op->Memory.OffsetImm = OffsetImm;
1660 Op->Memory.OffsetRegNum = OffsetRegNum;
1661 Op->Memory.ShiftType = ShiftType;
1662 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001663 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001664 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001665 Op->StartLoc = S;
1666 Op->EndLoc = E;
1667 return Op;
1668 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001669
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001670 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1671 ARM_AM::ShiftOpc ShiftTy,
1672 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001673 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001674 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001675 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001676 Op->PostIdxReg.isAdd = isAdd;
1677 Op->PostIdxReg.ShiftTy = ShiftTy;
1678 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001679 Op->StartLoc = S;
1680 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001681 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001682 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001683
1684 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001685 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001686 Op->MBOpt.Val = Opt;
1687 Op->StartLoc = S;
1688 Op->EndLoc = S;
1689 return Op;
1690 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001691
1692 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001693 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001694 Op->IFlags.Val = IFlags;
1695 Op->StartLoc = S;
1696 Op->EndLoc = S;
1697 return Op;
1698 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001699
1700 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001701 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001702 Op->MMask.Val = MMask;
1703 Op->StartLoc = S;
1704 Op->EndLoc = S;
1705 return Op;
1706 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001707};
1708
1709} // end anonymous namespace.
1710
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001711void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001712 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001713 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001714 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1715 << ") >";
1716 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001717 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001718 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001719 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001720 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001721 OS << "<ccout " << getReg() << ">";
1722 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001723 case k_ITCondMask: {
Jim Grosbach89df9962011-08-26 21:43:41 +00001724 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1725 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1726 "(tee)", "(eee)" };
1727 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1728 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1729 break;
1730 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001731 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001732 OS << "<coprocessor number: " << getCoproc() << ">";
1733 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001734 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001735 OS << "<coprocessor register: " << getCoproc() << ">";
1736 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001737 case k_CoprocOption:
1738 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1739 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001740 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001741 OS << "<mask: " << getMSRMask() << ">";
1742 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001743 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001744 getImm()->print(OS);
1745 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001746 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001747 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1748 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001749 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001750 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001751 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001752 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001753 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001754 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001755 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1756 << PostIdxReg.RegNum;
1757 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1758 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1759 << PostIdxReg.ShiftImm;
1760 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001761 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001762 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001763 OS << "<ARM_PROC::";
1764 unsigned IFlags = getProcIFlags();
1765 for (int i=2; i >= 0; --i)
1766 if (IFlags & (1 << i))
1767 OS << ARM_PROC::IFlagsToString(1 << i);
1768 OS << ">";
1769 break;
1770 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001771 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001772 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001773 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001774 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001775 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1776 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001777 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001778 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001779 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001780 << RegShiftedReg.SrcReg
1781 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1782 << ", " << RegShiftedReg.ShiftReg << ", "
1783 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001784 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001785 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001786 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001787 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001788 << RegShiftedImm.SrcReg
1789 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1790 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001791 << ">";
1792 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001793 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001794 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1795 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001796 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001797 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1798 << ", width: " << Bitfield.Width << ">";
1799 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001800 case k_RegisterList:
1801 case k_DPRRegisterList:
1802 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001803 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001804
Bill Wendling5fa22a12010-11-09 23:28:44 +00001805 const SmallVectorImpl<unsigned> &RegList = getRegList();
1806 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001807 I = RegList.begin(), E = RegList.end(); I != E; ) {
1808 OS << *I;
1809 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001810 }
1811
1812 OS << ">";
1813 break;
1814 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001815 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001816 OS << "'" << getToken() << "'";
1817 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001818 case k_VectorIndex:
1819 OS << "<vectorindex " << getVectorIndex() << ">";
1820 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001821 }
1822}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001823
1824/// @name Auto-generated Match Functions
1825/// {
1826
1827static unsigned MatchRegisterName(StringRef Name);
1828
1829/// }
1830
Bob Wilson69df7232011-02-03 21:46:10 +00001831bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1832 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001833 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001834
1835 return (RegNo == (unsigned)-1);
1836}
1837
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001838/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001839/// and if it is a register name the token is eaten and the register number is
1840/// returned. Otherwise return -1.
1841///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001842int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001843 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001844 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001845
Chris Lattnere5658fa2010-10-30 04:09:10 +00001846 // FIXME: Validate register for the current architecture; we have to do
1847 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00001848 std::string upperCase = Tok.getString().str();
1849 std::string lowerCase = LowercaseString(upperCase);
1850 unsigned RegNum = MatchRegisterName(lowerCase);
1851 if (!RegNum) {
1852 RegNum = StringSwitch<unsigned>(lowerCase)
1853 .Case("r13", ARM::SP)
1854 .Case("r14", ARM::LR)
1855 .Case("r15", ARM::PC)
1856 .Case("ip", ARM::R12)
1857 .Default(0);
1858 }
1859 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00001860
Chris Lattnere5658fa2010-10-30 04:09:10 +00001861 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00001862
1863#if 0
1864 // Also check for an index operand. This is only legal for vector registers,
1865 // but that'll get caught OK in operand matching, so we don't need to
1866 // explicitly filter everything else out here.
1867 if (Parser.getTok().is(AsmToken::LBrac)) {
1868 SMLoc SIdx = Parser.getTok().getLoc();
1869 Parser.Lex(); // Eat left bracket token.
1870
1871 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00001872 if (getParser().ParseExpression(ImmVal))
1873 return MatchOperand_ParseFail;
1874 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1875 if (!MCE) {
1876 TokError("immediate value expected for vector index");
1877 return MatchOperand_ParseFail;
1878 }
1879
1880 SMLoc E = Parser.getTok().getLoc();
1881 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1882 Error(E, "']' expected");
1883 return MatchOperand_ParseFail;
1884 }
1885
1886 Parser.Lex(); // Eat right bracket token.
1887
1888 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1889 SIdx, E,
1890 getContext()));
1891 }
1892#endif
1893
Chris Lattnere5658fa2010-10-30 04:09:10 +00001894 return RegNum;
1895}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001896
Jim Grosbach19906722011-07-13 18:49:30 +00001897// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1898// If a recoverable error occurs, return 1. If an irrecoverable error
1899// occurs, return -1. An irrecoverable error is one where tokens have been
1900// consumed in the process of trying to parse the shifter (i.e., when it is
1901// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00001902int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00001903 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1904 SMLoc S = Parser.getTok().getLoc();
1905 const AsmToken &Tok = Parser.getTok();
1906 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1907
1908 std::string upperCase = Tok.getString().str();
1909 std::string lowerCase = LowercaseString(upperCase);
1910 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1911 .Case("lsl", ARM_AM::lsl)
1912 .Case("lsr", ARM_AM::lsr)
1913 .Case("asr", ARM_AM::asr)
1914 .Case("ror", ARM_AM::ror)
1915 .Case("rrx", ARM_AM::rrx)
1916 .Default(ARM_AM::no_shift);
1917
1918 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00001919 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00001920
Jim Grosbache8606dc2011-07-13 17:50:29 +00001921 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00001922
Jim Grosbache8606dc2011-07-13 17:50:29 +00001923 // The source register for the shift has already been added to the
1924 // operand list, so we need to pop it off and combine it into the shifted
1925 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00001926 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00001927 if (!PrevOp->isReg())
1928 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1929 int SrcReg = PrevOp->getReg();
1930 int64_t Imm = 0;
1931 int ShiftReg = 0;
1932 if (ShiftTy == ARM_AM::rrx) {
1933 // RRX Doesn't have an explicit shift amount. The encoder expects
1934 // the shift register to be the same as the source register. Seems odd,
1935 // but OK.
1936 ShiftReg = SrcReg;
1937 } else {
1938 // Figure out if this is shifted by a constant or a register (for non-RRX).
1939 if (Parser.getTok().is(AsmToken::Hash)) {
1940 Parser.Lex(); // Eat hash.
1941 SMLoc ImmLoc = Parser.getTok().getLoc();
1942 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00001943 if (getParser().ParseExpression(ShiftExpr)) {
1944 Error(ImmLoc, "invalid immediate shift value");
1945 return -1;
1946 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001947 // The expression must be evaluatable as an immediate.
1948 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00001949 if (!CE) {
1950 Error(ImmLoc, "invalid immediate shift value");
1951 return -1;
1952 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001953 // Range check the immediate.
1954 // lsl, ror: 0 <= imm <= 31
1955 // lsr, asr: 0 <= imm <= 32
1956 Imm = CE->getValue();
1957 if (Imm < 0 ||
1958 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
1959 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00001960 Error(ImmLoc, "immediate shift value out of range");
1961 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001962 }
1963 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001964 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00001965 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00001966 if (ShiftReg == -1) {
1967 Error (L, "expected immediate or register in shift operand");
1968 return -1;
1969 }
1970 } else {
1971 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00001972 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00001973 return -1;
1974 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001975 }
1976
Owen Anderson92a20222011-07-21 18:54:16 +00001977 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1978 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001979 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001980 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00001981 else
1982 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1983 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00001984
Jim Grosbach19906722011-07-13 18:49:30 +00001985 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00001986}
1987
1988
Bill Wendling50d0f582010-11-18 23:43:05 +00001989/// Try to parse a register name. The token must be an Identifier when called.
1990/// If it's a register, an AsmOperand is created. Another AsmOperand is created
1991/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00001992///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001993/// TODO this is likely to change to allow different register types and or to
1994/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00001995bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001996tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001997 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00001998 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00001999 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002000 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002001
Bill Wendling50d0f582010-11-18 23:43:05 +00002002 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002003
Chris Lattnere5658fa2010-10-30 04:09:10 +00002004 const AsmToken &ExclaimTok = Parser.getTok();
2005 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002006 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2007 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002008 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002009 return false;
2010 }
2011
2012 // Also check for an index operand. This is only legal for vector registers,
2013 // but that'll get caught OK in operand matching, so we don't need to
2014 // explicitly filter everything else out here.
2015 if (Parser.getTok().is(AsmToken::LBrac)) {
2016 SMLoc SIdx = Parser.getTok().getLoc();
2017 Parser.Lex(); // Eat left bracket token.
2018
2019 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002020 if (getParser().ParseExpression(ImmVal))
2021 return MatchOperand_ParseFail;
2022 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2023 if (!MCE) {
2024 TokError("immediate value expected for vector index");
2025 return MatchOperand_ParseFail;
2026 }
2027
2028 SMLoc E = Parser.getTok().getLoc();
2029 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2030 Error(E, "']' expected");
2031 return MatchOperand_ParseFail;
2032 }
2033
2034 Parser.Lex(); // Eat right bracket token.
2035
2036 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2037 SIdx, E,
2038 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002039 }
2040
Bill Wendling50d0f582010-11-18 23:43:05 +00002041 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002042}
2043
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002044/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2045/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2046/// "c5", ...
2047static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002048 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2049 // but efficient.
2050 switch (Name.size()) {
2051 default: break;
2052 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002053 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002054 return -1;
2055 switch (Name[1]) {
2056 default: return -1;
2057 case '0': return 0;
2058 case '1': return 1;
2059 case '2': return 2;
2060 case '3': return 3;
2061 case '4': return 4;
2062 case '5': return 5;
2063 case '6': return 6;
2064 case '7': return 7;
2065 case '8': return 8;
2066 case '9': return 9;
2067 }
2068 break;
2069 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002070 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002071 return -1;
2072 switch (Name[2]) {
2073 default: return -1;
2074 case '0': return 10;
2075 case '1': return 11;
2076 case '2': return 12;
2077 case '3': return 13;
2078 case '4': return 14;
2079 case '5': return 15;
2080 }
2081 break;
2082 }
2083
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002084 return -1;
2085}
2086
Jim Grosbach89df9962011-08-26 21:43:41 +00002087/// parseITCondCode - Try to parse a condition code for an IT instruction.
2088ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2089parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2090 SMLoc S = Parser.getTok().getLoc();
2091 const AsmToken &Tok = Parser.getTok();
2092 if (!Tok.is(AsmToken::Identifier))
2093 return MatchOperand_NoMatch;
2094 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2095 .Case("eq", ARMCC::EQ)
2096 .Case("ne", ARMCC::NE)
2097 .Case("hs", ARMCC::HS)
2098 .Case("cs", ARMCC::HS)
2099 .Case("lo", ARMCC::LO)
2100 .Case("cc", ARMCC::LO)
2101 .Case("mi", ARMCC::MI)
2102 .Case("pl", ARMCC::PL)
2103 .Case("vs", ARMCC::VS)
2104 .Case("vc", ARMCC::VC)
2105 .Case("hi", ARMCC::HI)
2106 .Case("ls", ARMCC::LS)
2107 .Case("ge", ARMCC::GE)
2108 .Case("lt", ARMCC::LT)
2109 .Case("gt", ARMCC::GT)
2110 .Case("le", ARMCC::LE)
2111 .Case("al", ARMCC::AL)
2112 .Default(~0U);
2113 if (CC == ~0U)
2114 return MatchOperand_NoMatch;
2115 Parser.Lex(); // Eat the token.
2116
2117 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2118
2119 return MatchOperand_Success;
2120}
2121
Jim Grosbach43904292011-07-25 20:14:50 +00002122/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002123/// token must be an Identifier when called, and if it is a coprocessor
2124/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002125ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002126parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002127 SMLoc S = Parser.getTok().getLoc();
2128 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002129 if (Tok.isNot(AsmToken::Identifier))
2130 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002131
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002132 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002133 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002134 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002135
2136 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002137 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002138 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002139}
2140
Jim Grosbach43904292011-07-25 20:14:50 +00002141/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002142/// token must be an Identifier when called, and if it is a coprocessor
2143/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002144ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002145parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002146 SMLoc S = Parser.getTok().getLoc();
2147 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002148 if (Tok.isNot(AsmToken::Identifier))
2149 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002150
2151 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2152 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002153 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002154
2155 Parser.Lex(); // Eat identifier token.
2156 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002157 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002158}
2159
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002160/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2161/// coproc_option : '{' imm0_255 '}'
2162ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2163parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2164 SMLoc S = Parser.getTok().getLoc();
2165
2166 // If this isn't a '{', this isn't a coprocessor immediate operand.
2167 if (Parser.getTok().isNot(AsmToken::LCurly))
2168 return MatchOperand_NoMatch;
2169 Parser.Lex(); // Eat the '{'
2170
2171 const MCExpr *Expr;
2172 SMLoc Loc = Parser.getTok().getLoc();
2173 if (getParser().ParseExpression(Expr)) {
2174 Error(Loc, "illegal expression");
2175 return MatchOperand_ParseFail;
2176 }
2177 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2178 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2179 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2180 return MatchOperand_ParseFail;
2181 }
2182 int Val = CE->getValue();
2183
2184 // Check for and consume the closing '}'
2185 if (Parser.getTok().isNot(AsmToken::RCurly))
2186 return MatchOperand_ParseFail;
2187 SMLoc E = Parser.getTok().getLoc();
2188 Parser.Lex(); // Eat the '}'
2189
2190 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2191 return MatchOperand_Success;
2192}
2193
Jim Grosbachd0588e22011-09-14 18:08:35 +00002194// For register list parsing, we need to map from raw GPR register numbering
2195// to the enumeration values. The enumeration values aren't sorted by
2196// register number due to our using "sp", "lr" and "pc" as canonical names.
2197static unsigned getNextRegister(unsigned Reg) {
2198 // If this is a GPR, we need to do it manually, otherwise we can rely
2199 // on the sort ordering of the enumeration since the other reg-classes
2200 // are sane.
2201 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2202 return Reg + 1;
2203 switch(Reg) {
2204 default: assert(0 && "Invalid GPR number!");
2205 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2206 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2207 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2208 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2209 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2210 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2211 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2212 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2213 }
2214}
2215
2216/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002217bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002218parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002219 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002220 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002221 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002222 Parser.Lex(); // Eat '{' token.
2223 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002224
Jim Grosbachd0588e22011-09-14 18:08:35 +00002225 // Check the first register in the list to see what register class
2226 // this is a list of.
2227 int Reg = tryParseRegister();
2228 if (Reg == -1)
2229 return Error(RegLoc, "register expected");
2230
2231 MCRegisterClass *RC;
2232 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2233 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2234 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2235 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2236 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2237 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2238 else
2239 return Error(RegLoc, "invalid register in register list");
2240
2241 // The reglist instructions have at most 16 registers, so reserve
2242 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002243 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002244 // Store the first register.
2245 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002246
Jim Grosbachd0588e22011-09-14 18:08:35 +00002247 // This starts immediately after the first register token in the list,
2248 // so we can see either a comma or a minus (range separator) as a legal
2249 // next token.
2250 while (Parser.getTok().is(AsmToken::Comma) ||
2251 Parser.getTok().is(AsmToken::Minus)) {
2252 if (Parser.getTok().is(AsmToken::Minus)) {
2253 Parser.Lex(); // Eat the comma.
2254 SMLoc EndLoc = Parser.getTok().getLoc();
2255 int EndReg = tryParseRegister();
2256 if (EndReg == -1)
2257 return Error(EndLoc, "register expected");
2258 // If the register is the same as the start reg, there's nothing
2259 // more to do.
2260 if (Reg == EndReg)
2261 continue;
2262 // The register must be in the same register class as the first.
2263 if (!RC->contains(EndReg))
2264 return Error(EndLoc, "invalid register in register list");
2265 // Ranges must go from low to high.
2266 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2267 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002268
Jim Grosbachd0588e22011-09-14 18:08:35 +00002269 // Add all the registers in the range to the register list.
2270 while (Reg != EndReg) {
2271 Reg = getNextRegister(Reg);
2272 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2273 }
2274 continue;
2275 }
2276 Parser.Lex(); // Eat the comma.
2277 RegLoc = Parser.getTok().getLoc();
2278 int OldReg = Reg;
2279 Reg = tryParseRegister();
2280 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002281 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002282 // The register must be in the same register class as the first.
2283 if (!RC->contains(Reg))
2284 return Error(RegLoc, "invalid register in register list");
2285 // List must be monotonically increasing.
2286 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2287 return Error(RegLoc, "register list not in ascending order");
2288 // VFP register lists must also be contiguous.
2289 // It's OK to use the enumeration values directly here rather, as the
2290 // VFP register classes have the enum sorted properly.
2291 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2292 Reg != OldReg + 1)
2293 return Error(RegLoc, "non-contiguous register range");
2294 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002295 }
2296
Jim Grosbachd0588e22011-09-14 18:08:35 +00002297 SMLoc E = Parser.getTok().getLoc();
2298 if (Parser.getTok().isNot(AsmToken::RCurly))
2299 return Error(E, "'}' expected");
2300 Parser.Lex(); // Eat '}' token.
2301
Bill Wendling50d0f582010-11-18 23:43:05 +00002302 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2303 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002304}
2305
Jim Grosbach43904292011-07-25 20:14:50 +00002306/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002307ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002308parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002309 SMLoc S = Parser.getTok().getLoc();
2310 const AsmToken &Tok = Parser.getTok();
2311 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2312 StringRef OptStr = Tok.getString();
2313
2314 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2315 .Case("sy", ARM_MB::SY)
2316 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002317 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002318 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002319 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002320 .Case("ishst", ARM_MB::ISHST)
2321 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002322 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002323 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002324 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002325 .Case("osh", ARM_MB::OSH)
2326 .Case("oshst", ARM_MB::OSHST)
2327 .Default(~0U);
2328
2329 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002330 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002331
2332 Parser.Lex(); // Eat identifier token.
2333 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002334 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002335}
2336
Jim Grosbach43904292011-07-25 20:14:50 +00002337/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002338ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002339parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002340 SMLoc S = Parser.getTok().getLoc();
2341 const AsmToken &Tok = Parser.getTok();
2342 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2343 StringRef IFlagsStr = Tok.getString();
2344
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002345 // An iflags string of "none" is interpreted to mean that none of the AIF
2346 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002347 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002348 if (IFlagsStr != "none") {
2349 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2350 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2351 .Case("a", ARM_PROC::A)
2352 .Case("i", ARM_PROC::I)
2353 .Case("f", ARM_PROC::F)
2354 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002355
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002356 // If some specific iflag is already set, it means that some letter is
2357 // present more than once, this is not acceptable.
2358 if (Flag == ~0U || (IFlags & Flag))
2359 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002360
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002361 IFlags |= Flag;
2362 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002363 }
2364
2365 Parser.Lex(); // Eat identifier token.
2366 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2367 return MatchOperand_Success;
2368}
2369
Jim Grosbach43904292011-07-25 20:14:50 +00002370/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002371ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002372parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002373 SMLoc S = Parser.getTok().getLoc();
2374 const AsmToken &Tok = Parser.getTok();
2375 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2376 StringRef Mask = Tok.getString();
2377
James Molloyacad68d2011-09-28 14:21:38 +00002378 if (isMClass()) {
2379 // See ARMv6-M 10.1.1
2380 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2381 .Case("apsr", 0)
2382 .Case("iapsr", 1)
2383 .Case("eapsr", 2)
2384 .Case("xpsr", 3)
2385 .Case("ipsr", 5)
2386 .Case("epsr", 6)
2387 .Case("iepsr", 7)
2388 .Case("msp", 8)
2389 .Case("psp", 9)
2390 .Case("primask", 16)
2391 .Case("basepri", 17)
2392 .Case("basepri_max", 18)
2393 .Case("faultmask", 19)
2394 .Case("control", 20)
2395 .Default(~0U);
2396
2397 if (FlagsVal == ~0U)
2398 return MatchOperand_NoMatch;
2399
2400 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2401 // basepri, basepri_max and faultmask only valid for V7m.
2402 return MatchOperand_NoMatch;
2403
2404 Parser.Lex(); // Eat identifier token.
2405 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2406 return MatchOperand_Success;
2407 }
2408
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002409 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2410 size_t Start = 0, Next = Mask.find('_');
2411 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002412 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002413 if (Next != StringRef::npos)
2414 Flags = Mask.slice(Next+1, Mask.size());
2415
2416 // FlagsVal contains the complete mask:
2417 // 3-0: Mask
2418 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2419 unsigned FlagsVal = 0;
2420
2421 if (SpecReg == "apsr") {
2422 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002423 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002424 .Case("g", 0x4) // same as CPSR_s
2425 .Case("nzcvqg", 0xc) // same as CPSR_fs
2426 .Default(~0U);
2427
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002428 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002429 if (!Flags.empty())
2430 return MatchOperand_NoMatch;
2431 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002432 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002433 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002434 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002435 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2436 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002437 for (int i = 0, e = Flags.size(); i != e; ++i) {
2438 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2439 .Case("c", 1)
2440 .Case("x", 2)
2441 .Case("s", 4)
2442 .Case("f", 8)
2443 .Default(~0U);
2444
2445 // If some specific flag is already set, it means that some letter is
2446 // present more than once, this is not acceptable.
2447 if (FlagsVal == ~0U || (FlagsVal & Flag))
2448 return MatchOperand_NoMatch;
2449 FlagsVal |= Flag;
2450 }
2451 } else // No match for special register.
2452 return MatchOperand_NoMatch;
2453
2454 // Special register without flags are equivalent to "fc" flags.
2455 if (!FlagsVal)
2456 FlagsVal = 0x9;
2457
2458 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2459 if (SpecReg == "spsr")
2460 FlagsVal |= 16;
2461
2462 Parser.Lex(); // Eat identifier token.
2463 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2464 return MatchOperand_Success;
2465}
2466
Jim Grosbachf6c05252011-07-21 17:23:04 +00002467ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2468parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2469 int Low, int High) {
2470 const AsmToken &Tok = Parser.getTok();
2471 if (Tok.isNot(AsmToken::Identifier)) {
2472 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2473 return MatchOperand_ParseFail;
2474 }
2475 StringRef ShiftName = Tok.getString();
2476 std::string LowerOp = LowercaseString(Op);
2477 std::string UpperOp = UppercaseString(Op);
2478 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2479 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2480 return MatchOperand_ParseFail;
2481 }
2482 Parser.Lex(); // Eat shift type token.
2483
2484 // There must be a '#' and a shift amount.
2485 if (Parser.getTok().isNot(AsmToken::Hash)) {
2486 Error(Parser.getTok().getLoc(), "'#' expected");
2487 return MatchOperand_ParseFail;
2488 }
2489 Parser.Lex(); // Eat hash token.
2490
2491 const MCExpr *ShiftAmount;
2492 SMLoc Loc = Parser.getTok().getLoc();
2493 if (getParser().ParseExpression(ShiftAmount)) {
2494 Error(Loc, "illegal expression");
2495 return MatchOperand_ParseFail;
2496 }
2497 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2498 if (!CE) {
2499 Error(Loc, "constant expression expected");
2500 return MatchOperand_ParseFail;
2501 }
2502 int Val = CE->getValue();
2503 if (Val < Low || Val > High) {
2504 Error(Loc, "immediate value out of range");
2505 return MatchOperand_ParseFail;
2506 }
2507
2508 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2509
2510 return MatchOperand_Success;
2511}
2512
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002513ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2514parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2515 const AsmToken &Tok = Parser.getTok();
2516 SMLoc S = Tok.getLoc();
2517 if (Tok.isNot(AsmToken::Identifier)) {
2518 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2519 return MatchOperand_ParseFail;
2520 }
2521 int Val = StringSwitch<int>(Tok.getString())
2522 .Case("be", 1)
2523 .Case("le", 0)
2524 .Default(-1);
2525 Parser.Lex(); // Eat the token.
2526
2527 if (Val == -1) {
2528 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2529 return MatchOperand_ParseFail;
2530 }
2531 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2532 getContext()),
2533 S, Parser.getTok().getLoc()));
2534 return MatchOperand_Success;
2535}
2536
Jim Grosbach580f4a92011-07-25 22:20:28 +00002537/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2538/// instructions. Legal values are:
2539/// lsl #n 'n' in [0,31]
2540/// asr #n 'n' in [1,32]
2541/// n == 32 encoded as n == 0.
2542ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2543parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2544 const AsmToken &Tok = Parser.getTok();
2545 SMLoc S = Tok.getLoc();
2546 if (Tok.isNot(AsmToken::Identifier)) {
2547 Error(S, "shift operator 'asr' or 'lsl' expected");
2548 return MatchOperand_ParseFail;
2549 }
2550 StringRef ShiftName = Tok.getString();
2551 bool isASR;
2552 if (ShiftName == "lsl" || ShiftName == "LSL")
2553 isASR = false;
2554 else if (ShiftName == "asr" || ShiftName == "ASR")
2555 isASR = true;
2556 else {
2557 Error(S, "shift operator 'asr' or 'lsl' expected");
2558 return MatchOperand_ParseFail;
2559 }
2560 Parser.Lex(); // Eat the operator.
2561
2562 // A '#' and a shift amount.
2563 if (Parser.getTok().isNot(AsmToken::Hash)) {
2564 Error(Parser.getTok().getLoc(), "'#' expected");
2565 return MatchOperand_ParseFail;
2566 }
2567 Parser.Lex(); // Eat hash token.
2568
2569 const MCExpr *ShiftAmount;
2570 SMLoc E = Parser.getTok().getLoc();
2571 if (getParser().ParseExpression(ShiftAmount)) {
2572 Error(E, "malformed shift expression");
2573 return MatchOperand_ParseFail;
2574 }
2575 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2576 if (!CE) {
2577 Error(E, "shift amount must be an immediate");
2578 return MatchOperand_ParseFail;
2579 }
2580
2581 int64_t Val = CE->getValue();
2582 if (isASR) {
2583 // Shift amount must be in [1,32]
2584 if (Val < 1 || Val > 32) {
2585 Error(E, "'asr' shift amount must be in range [1,32]");
2586 return MatchOperand_ParseFail;
2587 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002588 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2589 if (isThumb() && Val == 32) {
2590 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2591 return MatchOperand_ParseFail;
2592 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002593 if (Val == 32) Val = 0;
2594 } else {
2595 // Shift amount must be in [1,32]
2596 if (Val < 0 || Val > 31) {
2597 Error(E, "'lsr' shift amount must be in range [0,31]");
2598 return MatchOperand_ParseFail;
2599 }
2600 }
2601
2602 E = Parser.getTok().getLoc();
2603 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2604
2605 return MatchOperand_Success;
2606}
2607
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002608/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2609/// of instructions. Legal values are:
2610/// ror #n 'n' in {0, 8, 16, 24}
2611ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2612parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2613 const AsmToken &Tok = Parser.getTok();
2614 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002615 if (Tok.isNot(AsmToken::Identifier))
2616 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002617 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002618 if (ShiftName != "ror" && ShiftName != "ROR")
2619 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002620 Parser.Lex(); // Eat the operator.
2621
2622 // A '#' and a rotate amount.
2623 if (Parser.getTok().isNot(AsmToken::Hash)) {
2624 Error(Parser.getTok().getLoc(), "'#' expected");
2625 return MatchOperand_ParseFail;
2626 }
2627 Parser.Lex(); // Eat hash token.
2628
2629 const MCExpr *ShiftAmount;
2630 SMLoc E = Parser.getTok().getLoc();
2631 if (getParser().ParseExpression(ShiftAmount)) {
2632 Error(E, "malformed rotate expression");
2633 return MatchOperand_ParseFail;
2634 }
2635 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2636 if (!CE) {
2637 Error(E, "rotate amount must be an immediate");
2638 return MatchOperand_ParseFail;
2639 }
2640
2641 int64_t Val = CE->getValue();
2642 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2643 // normally, zero is represented in asm by omitting the rotate operand
2644 // entirely.
2645 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2646 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2647 return MatchOperand_ParseFail;
2648 }
2649
2650 E = Parser.getTok().getLoc();
2651 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2652
2653 return MatchOperand_Success;
2654}
2655
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002656ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2657parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2658 SMLoc S = Parser.getTok().getLoc();
2659 // The bitfield descriptor is really two operands, the LSB and the width.
2660 if (Parser.getTok().isNot(AsmToken::Hash)) {
2661 Error(Parser.getTok().getLoc(), "'#' expected");
2662 return MatchOperand_ParseFail;
2663 }
2664 Parser.Lex(); // Eat hash token.
2665
2666 const MCExpr *LSBExpr;
2667 SMLoc E = Parser.getTok().getLoc();
2668 if (getParser().ParseExpression(LSBExpr)) {
2669 Error(E, "malformed immediate expression");
2670 return MatchOperand_ParseFail;
2671 }
2672 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2673 if (!CE) {
2674 Error(E, "'lsb' operand must be an immediate");
2675 return MatchOperand_ParseFail;
2676 }
2677
2678 int64_t LSB = CE->getValue();
2679 // The LSB must be in the range [0,31]
2680 if (LSB < 0 || LSB > 31) {
2681 Error(E, "'lsb' operand must be in the range [0,31]");
2682 return MatchOperand_ParseFail;
2683 }
2684 E = Parser.getTok().getLoc();
2685
2686 // Expect another immediate operand.
2687 if (Parser.getTok().isNot(AsmToken::Comma)) {
2688 Error(Parser.getTok().getLoc(), "too few operands");
2689 return MatchOperand_ParseFail;
2690 }
2691 Parser.Lex(); // Eat hash token.
2692 if (Parser.getTok().isNot(AsmToken::Hash)) {
2693 Error(Parser.getTok().getLoc(), "'#' expected");
2694 return MatchOperand_ParseFail;
2695 }
2696 Parser.Lex(); // Eat hash token.
2697
2698 const MCExpr *WidthExpr;
2699 if (getParser().ParseExpression(WidthExpr)) {
2700 Error(E, "malformed immediate expression");
2701 return MatchOperand_ParseFail;
2702 }
2703 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2704 if (!CE) {
2705 Error(E, "'width' operand must be an immediate");
2706 return MatchOperand_ParseFail;
2707 }
2708
2709 int64_t Width = CE->getValue();
2710 // The LSB must be in the range [1,32-lsb]
2711 if (Width < 1 || Width > 32 - LSB) {
2712 Error(E, "'width' operand must be in the range [1,32-lsb]");
2713 return MatchOperand_ParseFail;
2714 }
2715 E = Parser.getTok().getLoc();
2716
2717 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2718
2719 return MatchOperand_Success;
2720}
2721
Jim Grosbach7ce05792011-08-03 23:50:40 +00002722ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2723parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2724 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002725 // postidx_reg := '+' register {, shift}
2726 // | '-' register {, shift}
2727 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002728
2729 // This method must return MatchOperand_NoMatch without consuming any tokens
2730 // in the case where there is no match, as other alternatives take other
2731 // parse methods.
2732 AsmToken Tok = Parser.getTok();
2733 SMLoc S = Tok.getLoc();
2734 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002735 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002736 int Reg = -1;
2737 if (Tok.is(AsmToken::Plus)) {
2738 Parser.Lex(); // Eat the '+' token.
2739 haveEaten = true;
2740 } else if (Tok.is(AsmToken::Minus)) {
2741 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002742 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002743 haveEaten = true;
2744 }
2745 if (Parser.getTok().is(AsmToken::Identifier))
2746 Reg = tryParseRegister();
2747 if (Reg == -1) {
2748 if (!haveEaten)
2749 return MatchOperand_NoMatch;
2750 Error(Parser.getTok().getLoc(), "register expected");
2751 return MatchOperand_ParseFail;
2752 }
2753 SMLoc E = Parser.getTok().getLoc();
2754
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002755 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2756 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002757 if (Parser.getTok().is(AsmToken::Comma)) {
2758 Parser.Lex(); // Eat the ','.
2759 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2760 return MatchOperand_ParseFail;
2761 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002762
2763 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2764 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002765
2766 return MatchOperand_Success;
2767}
2768
Jim Grosbach251bf252011-08-10 21:56:18 +00002769ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2770parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2771 // Check for a post-index addressing register operand. Specifically:
2772 // am3offset := '+' register
2773 // | '-' register
2774 // | register
2775 // | # imm
2776 // | # + imm
2777 // | # - imm
2778
2779 // This method must return MatchOperand_NoMatch without consuming any tokens
2780 // in the case where there is no match, as other alternatives take other
2781 // parse methods.
2782 AsmToken Tok = Parser.getTok();
2783 SMLoc S = Tok.getLoc();
2784
2785 // Do immediates first, as we always parse those if we have a '#'.
2786 if (Parser.getTok().is(AsmToken::Hash)) {
2787 Parser.Lex(); // Eat the '#'.
2788 // Explicitly look for a '-', as we need to encode negative zero
2789 // differently.
2790 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2791 const MCExpr *Offset;
2792 if (getParser().ParseExpression(Offset))
2793 return MatchOperand_ParseFail;
2794 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2795 if (!CE) {
2796 Error(S, "constant expression expected");
2797 return MatchOperand_ParseFail;
2798 }
2799 SMLoc E = Tok.getLoc();
2800 // Negative zero is encoded as the flag value INT32_MIN.
2801 int32_t Val = CE->getValue();
2802 if (isNegative && Val == 0)
2803 Val = INT32_MIN;
2804
2805 Operands.push_back(
2806 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2807
2808 return MatchOperand_Success;
2809 }
2810
2811
2812 bool haveEaten = false;
2813 bool isAdd = true;
2814 int Reg = -1;
2815 if (Tok.is(AsmToken::Plus)) {
2816 Parser.Lex(); // Eat the '+' token.
2817 haveEaten = true;
2818 } else if (Tok.is(AsmToken::Minus)) {
2819 Parser.Lex(); // Eat the '-' token.
2820 isAdd = false;
2821 haveEaten = true;
2822 }
2823 if (Parser.getTok().is(AsmToken::Identifier))
2824 Reg = tryParseRegister();
2825 if (Reg == -1) {
2826 if (!haveEaten)
2827 return MatchOperand_NoMatch;
2828 Error(Parser.getTok().getLoc(), "register expected");
2829 return MatchOperand_ParseFail;
2830 }
2831 SMLoc E = Parser.getTok().getLoc();
2832
2833 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2834 0, S, E));
2835
2836 return MatchOperand_Success;
2837}
2838
Jim Grosbacha77295d2011-09-08 22:07:06 +00002839/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2840/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2841/// when they refer multiple MIOperands inside a single one.
2842bool ARMAsmParser::
2843cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2844 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2845 // Rt, Rt2
2846 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2847 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2848 // Create a writeback register dummy placeholder.
2849 Inst.addOperand(MCOperand::CreateReg(0));
2850 // addr
2851 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2852 // pred
2853 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2854 return true;
2855}
2856
2857/// cvtT2StrdPre - Convert parsed operands to MCInst.
2858/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2859/// when they refer multiple MIOperands inside a single one.
2860bool ARMAsmParser::
2861cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2862 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2863 // Create a writeback register dummy placeholder.
2864 Inst.addOperand(MCOperand::CreateReg(0));
2865 // Rt, Rt2
2866 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2867 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2868 // addr
2869 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2870 // pred
2871 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2872 return true;
2873}
2874
Jim Grosbacheeec0252011-09-08 00:39:19 +00002875/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2876/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2877/// when they refer multiple MIOperands inside a single one.
2878bool ARMAsmParser::
2879cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2880 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2881 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2882
2883 // Create a writeback register dummy placeholder.
2884 Inst.addOperand(MCOperand::CreateImm(0));
2885
2886 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2887 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2888 return true;
2889}
2890
Jim Grosbachee2c2a42011-09-16 21:55:56 +00002891/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2892/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2893/// when they refer multiple MIOperands inside a single one.
2894bool ARMAsmParser::
2895cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2896 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2897 // Create a writeback register dummy placeholder.
2898 Inst.addOperand(MCOperand::CreateImm(0));
2899 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2900 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2901 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2902 return true;
2903}
2904
Jim Grosbach1355cf12011-07-26 17:10:22 +00002905/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002906/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2907/// when they refer multiple MIOperands inside a single one.
2908bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002909cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002910 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2911 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2912
2913 // Create a writeback register dummy placeholder.
2914 Inst.addOperand(MCOperand::CreateImm(0));
2915
Jim Grosbach7ce05792011-08-03 23:50:40 +00002916 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002917 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2918 return true;
2919}
2920
Owen Anderson9ab0f252011-08-26 20:43:14 +00002921/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2922/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2923/// when they refer multiple MIOperands inside a single one.
2924bool ARMAsmParser::
2925cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2926 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2927 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2928
2929 // Create a writeback register dummy placeholder.
2930 Inst.addOperand(MCOperand::CreateImm(0));
2931
2932 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2933 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2934 return true;
2935}
2936
2937
Jim Grosbach548340c2011-08-11 19:22:40 +00002938/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2939/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2940/// when they refer multiple MIOperands inside a single one.
2941bool ARMAsmParser::
2942cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2943 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2944 // Create a writeback register dummy placeholder.
2945 Inst.addOperand(MCOperand::CreateImm(0));
2946 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2947 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2948 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2949 return true;
2950}
2951
Jim Grosbach1355cf12011-07-26 17:10:22 +00002952/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002953/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2954/// when they refer multiple MIOperands inside a single one.
2955bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002956cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002957 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2958 // Create a writeback register dummy placeholder.
2959 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00002960 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2961 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2962 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002963 return true;
2964}
2965
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00002966/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2967/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2968/// when they refer multiple MIOperands inside a single one.
2969bool ARMAsmParser::
2970cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2971 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2972 // Create a writeback register dummy placeholder.
2973 Inst.addOperand(MCOperand::CreateImm(0));
2974 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2975 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2976 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2977 return true;
2978}
2979
Jim Grosbach7ce05792011-08-03 23:50:40 +00002980/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2981/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2982/// when they refer multiple MIOperands inside a single one.
2983bool ARMAsmParser::
2984cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2985 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2986 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002987 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002988 // Create a writeback register dummy placeholder.
2989 Inst.addOperand(MCOperand::CreateImm(0));
2990 // addr
2991 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2992 // offset
2993 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2994 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002995 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2996 return true;
2997}
2998
Jim Grosbach7ce05792011-08-03 23:50:40 +00002999/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003000/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3001/// when they refer multiple MIOperands inside a single one.
3002bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003003cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3004 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3005 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003006 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003007 // Create a writeback register dummy placeholder.
3008 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003009 // addr
3010 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3011 // offset
3012 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3013 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003014 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3015 return true;
3016}
3017
Jim Grosbach7ce05792011-08-03 23:50:40 +00003018/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003019/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3020/// when they refer multiple MIOperands inside a single one.
3021bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003022cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3023 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003024 // Create a writeback register dummy placeholder.
3025 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003026 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003027 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003028 // addr
3029 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3030 // offset
3031 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3032 // pred
3033 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3034 return true;
3035}
3036
3037/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3038/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3039/// when they refer multiple MIOperands inside a single one.
3040bool ARMAsmParser::
3041cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3042 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3043 // Create a writeback register dummy placeholder.
3044 Inst.addOperand(MCOperand::CreateImm(0));
3045 // Rt
3046 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3047 // addr
3048 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3049 // offset
3050 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3051 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003052 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3053 return true;
3054}
3055
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003056/// cvtLdrdPre - Convert parsed operands to MCInst.
3057/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3058/// when they refer multiple MIOperands inside a single one.
3059bool ARMAsmParser::
3060cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3061 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3062 // Rt, Rt2
3063 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3064 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3065 // Create a writeback register dummy placeholder.
3066 Inst.addOperand(MCOperand::CreateImm(0));
3067 // addr
3068 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3069 // pred
3070 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3071 return true;
3072}
3073
Jim Grosbach14605d12011-08-11 20:28:23 +00003074/// cvtStrdPre - Convert parsed operands to MCInst.
3075/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3076/// when they refer multiple MIOperands inside a single one.
3077bool ARMAsmParser::
3078cvtStrdPre(MCInst &Inst, unsigned Opcode,
3079 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3080 // Create a writeback register dummy placeholder.
3081 Inst.addOperand(MCOperand::CreateImm(0));
3082 // Rt, Rt2
3083 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3084 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3085 // addr
3086 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3087 // pred
3088 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3089 return true;
3090}
3091
Jim Grosbach623a4542011-08-10 22:42:16 +00003092/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3093/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3094/// when they refer multiple MIOperands inside a single one.
3095bool ARMAsmParser::
3096cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3097 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3098 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3099 // Create a writeback register dummy placeholder.
3100 Inst.addOperand(MCOperand::CreateImm(0));
3101 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3102 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3103 return true;
3104}
3105
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003106/// cvtThumbMultiple- Convert parsed operands to MCInst.
3107/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3108/// when they refer multiple MIOperands inside a single one.
3109bool ARMAsmParser::
3110cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3111 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3112 // The second source operand must be the same register as the destination
3113 // operand.
3114 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003115 (((ARMOperand*)Operands[3])->getReg() !=
3116 ((ARMOperand*)Operands[5])->getReg()) &&
3117 (((ARMOperand*)Operands[3])->getReg() !=
3118 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003119 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003120 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003121 return false;
3122 }
3123 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3124 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3125 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003126 // If we have a three-operand form, use that, else the second source operand
3127 // is just the destination operand again.
3128 if (Operands.size() == 6)
3129 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3130 else
3131 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003132 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3133
3134 return true;
3135}
Jim Grosbach623a4542011-08-10 22:42:16 +00003136
Bill Wendlinge7176102010-11-06 22:36:58 +00003137/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003138/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003139bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003140parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003141 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003142 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003143 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003144 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003145 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003146
Sean Callanan18b83232010-01-19 21:44:56 +00003147 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003148 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003149 if (BaseRegNum == -1)
3150 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003151
Daniel Dunbar05710932011-01-18 05:34:17 +00003152 // The next token must either be a comma or a closing bracket.
3153 const AsmToken &Tok = Parser.getTok();
3154 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003155 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003156
Jim Grosbach7ce05792011-08-03 23:50:40 +00003157 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003158 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003159 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003160
Jim Grosbach7ce05792011-08-03 23:50:40 +00003161 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003162 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003163
Jim Grosbachfb12f352011-09-19 18:42:21 +00003164 // If there's a pre-indexing writeback marker, '!', just add it as a token
3165 // operand. It's rather odd, but syntactically valid.
3166 if (Parser.getTok().is(AsmToken::Exclaim)) {
3167 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3168 Parser.Lex(); // Eat the '!'.
3169 }
3170
Jim Grosbach7ce05792011-08-03 23:50:40 +00003171 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003172 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003173
Jim Grosbach7ce05792011-08-03 23:50:40 +00003174 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3175 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003176
Jim Grosbach57dcb852011-10-11 17:29:55 +00003177 // If we have a ':', it's an alignment specifier.
3178 if (Parser.getTok().is(AsmToken::Colon)) {
3179 Parser.Lex(); // Eat the ':'.
3180 E = Parser.getTok().getLoc();
3181
3182 const MCExpr *Expr;
3183 if (getParser().ParseExpression(Expr))
3184 return true;
3185
3186 // The expression has to be a constant. Memory references with relocations
3187 // don't come through here, as they use the <label> forms of the relevant
3188 // instructions.
3189 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3190 if (!CE)
3191 return Error (E, "constant expression expected");
3192
3193 unsigned Align = 0;
3194 switch (CE->getValue()) {
3195 default:
3196 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3197 case 64: Align = 8; break;
3198 case 128: Align = 16; break;
3199 case 256: Align = 32; break;
3200 }
3201
3202 // Now we should have the closing ']'
3203 E = Parser.getTok().getLoc();
3204 if (Parser.getTok().isNot(AsmToken::RBrac))
3205 return Error(E, "']' expected");
3206 Parser.Lex(); // Eat right bracket token.
3207
3208 // Don't worry about range checking the value here. That's handled by
3209 // the is*() predicates.
3210 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3211 ARM_AM::no_shift, 0, Align,
3212 false, S, E));
3213
3214 // If there's a pre-indexing writeback marker, '!', just add it as a token
3215 // operand.
3216 if (Parser.getTok().is(AsmToken::Exclaim)) {
3217 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3218 Parser.Lex(); // Eat the '!'.
3219 }
3220
3221 return false;
3222 }
3223
3224 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003225 // offset.
3226 if (Parser.getTok().is(AsmToken::Hash)) {
3227 Parser.Lex(); // Eat the '#'.
3228 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003229
Owen Anderson0da10cf2011-08-29 19:36:44 +00003230 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003231 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003232 if (getParser().ParseExpression(Offset))
3233 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003234
3235 // The expression has to be a constant. Memory references with relocations
3236 // don't come through here, as they use the <label> forms of the relevant
3237 // instructions.
3238 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3239 if (!CE)
3240 return Error (E, "constant expression expected");
3241
Owen Anderson0da10cf2011-08-29 19:36:44 +00003242 // If the constant was #-0, represent it as INT32_MIN.
3243 int32_t Val = CE->getValue();
3244 if (isNegative && Val == 0)
3245 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3246
Jim Grosbach7ce05792011-08-03 23:50:40 +00003247 // Now we should have the closing ']'
3248 E = Parser.getTok().getLoc();
3249 if (Parser.getTok().isNot(AsmToken::RBrac))
3250 return Error(E, "']' expected");
3251 Parser.Lex(); // Eat right bracket token.
3252
3253 // Don't worry about range checking the value here. That's handled by
3254 // the is*() predicates.
3255 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003256 ARM_AM::no_shift, 0, 0,
3257 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003258
3259 // If there's a pre-indexing writeback marker, '!', just add it as a token
3260 // operand.
3261 if (Parser.getTok().is(AsmToken::Exclaim)) {
3262 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3263 Parser.Lex(); // Eat the '!'.
3264 }
3265
3266 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003267 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003268
3269 // The register offset is optionally preceded by a '+' or '-'
3270 bool isNegative = false;
3271 if (Parser.getTok().is(AsmToken::Minus)) {
3272 isNegative = true;
3273 Parser.Lex(); // Eat the '-'.
3274 } else if (Parser.getTok().is(AsmToken::Plus)) {
3275 // Nothing to do.
3276 Parser.Lex(); // Eat the '+'.
3277 }
3278
3279 E = Parser.getTok().getLoc();
3280 int OffsetRegNum = tryParseRegister();
3281 if (OffsetRegNum == -1)
3282 return Error(E, "register expected");
3283
3284 // If there's a shift operator, handle it.
3285 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003286 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003287 if (Parser.getTok().is(AsmToken::Comma)) {
3288 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003289 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003290 return true;
3291 }
3292
3293 // Now we should have the closing ']'
3294 E = Parser.getTok().getLoc();
3295 if (Parser.getTok().isNot(AsmToken::RBrac))
3296 return Error(E, "']' expected");
3297 Parser.Lex(); // Eat right bracket token.
3298
3299 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003300 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003301 S, E));
3302
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003303 // If there's a pre-indexing writeback marker, '!', just add it as a token
3304 // operand.
3305 if (Parser.getTok().is(AsmToken::Exclaim)) {
3306 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3307 Parser.Lex(); // Eat the '!'.
3308 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003309
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003310 return false;
3311}
3312
Jim Grosbach7ce05792011-08-03 23:50:40 +00003313/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003314/// ( lsl | lsr | asr | ror ) , # shift_amount
3315/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003316/// return true if it parses a shift otherwise it returns false.
3317bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3318 unsigned &Amount) {
3319 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003320 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003321 if (Tok.isNot(AsmToken::Identifier))
3322 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003323 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003324 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003325 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003326 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003327 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003328 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003329 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003330 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003331 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003332 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003333 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003334 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003335 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003336 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003337
Jim Grosbach7ce05792011-08-03 23:50:40 +00003338 // rrx stands alone.
3339 Amount = 0;
3340 if (St != ARM_AM::rrx) {
3341 Loc = Parser.getTok().getLoc();
3342 // A '#' and a shift amount.
3343 const AsmToken &HashTok = Parser.getTok();
3344 if (HashTok.isNot(AsmToken::Hash))
3345 return Error(HashTok.getLoc(), "'#' expected");
3346 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003347
Jim Grosbach7ce05792011-08-03 23:50:40 +00003348 const MCExpr *Expr;
3349 if (getParser().ParseExpression(Expr))
3350 return true;
3351 // Range check the immediate.
3352 // lsl, ror: 0 <= imm <= 31
3353 // lsr, asr: 0 <= imm <= 32
3354 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3355 if (!CE)
3356 return Error(Loc, "shift amount must be an immediate");
3357 int64_t Imm = CE->getValue();
3358 if (Imm < 0 ||
3359 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3360 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3361 return Error(Loc, "immediate shift value out of range");
3362 Amount = Imm;
3363 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003364
3365 return false;
3366}
3367
Jim Grosbach9d390362011-10-03 23:38:36 +00003368/// parseFPImm - A floating point immediate expression operand.
3369ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3370parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3371 SMLoc S = Parser.getTok().getLoc();
3372
3373 if (Parser.getTok().isNot(AsmToken::Hash))
3374 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003375
3376 // Disambiguate the VMOV forms that can accept an FP immediate.
3377 // vmov.f32 <sreg>, #imm
3378 // vmov.f64 <dreg>, #imm
3379 // vmov.f32 <dreg>, #imm @ vector f32x2
3380 // vmov.f32 <qreg>, #imm @ vector f32x4
3381 //
3382 // There are also the NEON VMOV instructions which expect an
3383 // integer constant. Make sure we don't try to parse an FPImm
3384 // for these:
3385 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3386 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3387 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3388 TyOp->getToken() != ".f64"))
3389 return MatchOperand_NoMatch;
3390
Jim Grosbach9d390362011-10-03 23:38:36 +00003391 Parser.Lex(); // Eat the '#'.
3392
3393 // Handle negation, as that still comes through as a separate token.
3394 bool isNegative = false;
3395 if (Parser.getTok().is(AsmToken::Minus)) {
3396 isNegative = true;
3397 Parser.Lex();
3398 }
3399 const AsmToken &Tok = Parser.getTok();
3400 if (Tok.is(AsmToken::Real)) {
3401 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3402 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3403 // If we had a '-' in front, toggle the sign bit.
3404 IntVal ^= (uint64_t)isNegative << 63;
3405 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3406 Parser.Lex(); // Eat the token.
3407 if (Val == -1) {
3408 TokError("floating point value out of range");
3409 return MatchOperand_ParseFail;
3410 }
3411 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3412 return MatchOperand_Success;
3413 }
3414 if (Tok.is(AsmToken::Integer)) {
3415 int64_t Val = Tok.getIntVal();
3416 Parser.Lex(); // Eat the token.
3417 if (Val > 255 || Val < 0) {
3418 TokError("encoded floating point value out of range");
3419 return MatchOperand_ParseFail;
3420 }
3421 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3422 return MatchOperand_Success;
3423 }
3424
3425 TokError("invalid floating point immediate");
3426 return MatchOperand_ParseFail;
3427}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003428/// Parse a arm instruction operand. For now this parses the operand regardless
3429/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003430bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003431 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003432 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003433
3434 // Check if the current operand has a custom associated parser, if so, try to
3435 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003436 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3437 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003438 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003439 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3440 // there was a match, but an error occurred, in which case, just return that
3441 // the operand parsing failed.
3442 if (ResTy == MatchOperand_ParseFail)
3443 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003444
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003445 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003446 default:
3447 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003448 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003449 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003450 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003451 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003452 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003453 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003454 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003455 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003456 else if (Res == -1) // irrecoverable error
3457 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003458 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3459 S = Parser.getTok().getLoc();
3460 Parser.Lex();
3461 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3462 return false;
3463 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003464
3465 // Fall though for the Identifier case that is not a register or a
3466 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003467 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003468 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3469 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003470 // This was not a register so parse other operands that start with an
3471 // identifier (like labels) as expressions and create them as immediates.
3472 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003473 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003474 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003475 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003476 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003477 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3478 return false;
3479 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003480 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003481 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003482 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003483 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003484 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003485 // #42 -> immediate.
3486 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003487 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003488 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003489 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003490 const MCExpr *ImmVal;
3491 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003492 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003493 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3494 if (!CE) {
3495 Error(S, "constant expression expected");
3496 return MatchOperand_ParseFail;
3497 }
3498 int32_t Val = CE->getValue();
3499 if (isNegative && Val == 0)
3500 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003501 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003502 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3503 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003504 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003505 case AsmToken::Colon: {
3506 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003507 // FIXME: Check it's an expression prefix,
3508 // e.g. (FOO - :lower16:BAR) isn't legal.
3509 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003510 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003511 return true;
3512
Evan Cheng75972122011-01-13 07:58:56 +00003513 const MCExpr *SubExprVal;
3514 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003515 return true;
3516
Evan Cheng75972122011-01-13 07:58:56 +00003517 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3518 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003519 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003520 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003521 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003522 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003523 }
3524}
3525
Jim Grosbach1355cf12011-07-26 17:10:22 +00003526// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003527// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003528bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003529 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003530
3531 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003532 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003533 Parser.Lex(); // Eat ':'
3534
3535 if (getLexer().isNot(AsmToken::Identifier)) {
3536 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3537 return true;
3538 }
3539
3540 StringRef IDVal = Parser.getTok().getIdentifier();
3541 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003542 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003543 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003544 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003545 } else {
3546 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3547 return true;
3548 }
3549 Parser.Lex();
3550
3551 if (getLexer().isNot(AsmToken::Colon)) {
3552 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3553 return true;
3554 }
3555 Parser.Lex(); // Eat the last ':'
3556 return false;
3557}
3558
Daniel Dunbar352e1482011-01-11 15:59:50 +00003559/// \brief Given a mnemonic, split out possible predication code and carry
3560/// setting letters to form a canonical mnemonic and flags.
3561//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003562// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003563// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003564StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003565 unsigned &PredicationCode,
3566 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003567 unsigned &ProcessorIMod,
3568 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003569 PredicationCode = ARMCC::AL;
3570 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003571 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003572
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003573 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003574 //
3575 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003576 if ((Mnemonic == "movs" && isThumb()) ||
3577 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3578 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3579 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3580 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3581 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3582 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3583 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003584 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003585
Jim Grosbach3f00e312011-07-11 17:09:57 +00003586 // First, split out any predication code. Ignore mnemonics we know aren't
3587 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003588 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003589 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003590 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003591 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003592 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3593 .Case("eq", ARMCC::EQ)
3594 .Case("ne", ARMCC::NE)
3595 .Case("hs", ARMCC::HS)
3596 .Case("cs", ARMCC::HS)
3597 .Case("lo", ARMCC::LO)
3598 .Case("cc", ARMCC::LO)
3599 .Case("mi", ARMCC::MI)
3600 .Case("pl", ARMCC::PL)
3601 .Case("vs", ARMCC::VS)
3602 .Case("vc", ARMCC::VC)
3603 .Case("hi", ARMCC::HI)
3604 .Case("ls", ARMCC::LS)
3605 .Case("ge", ARMCC::GE)
3606 .Case("lt", ARMCC::LT)
3607 .Case("gt", ARMCC::GT)
3608 .Case("le", ARMCC::LE)
3609 .Case("al", ARMCC::AL)
3610 .Default(~0U);
3611 if (CC != ~0U) {
3612 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3613 PredicationCode = CC;
3614 }
Bill Wendling52925b62010-10-29 23:50:21 +00003615 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003616
Daniel Dunbar352e1482011-01-11 15:59:50 +00003617 // Next, determine if we have a carry setting bit. We explicitly ignore all
3618 // the instructions we know end in 's'.
3619 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003620 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003621 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3622 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3623 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003624 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3625 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003626 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3627 CarrySetting = true;
3628 }
3629
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003630 // The "cps" instruction can have a interrupt mode operand which is glued into
3631 // the mnemonic. Check if this is the case, split it and parse the imod op
3632 if (Mnemonic.startswith("cps")) {
3633 // Split out any imod code.
3634 unsigned IMod =
3635 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3636 .Case("ie", ARM_PROC::IE)
3637 .Case("id", ARM_PROC::ID)
3638 .Default(~0U);
3639 if (IMod != ~0U) {
3640 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3641 ProcessorIMod = IMod;
3642 }
3643 }
3644
Jim Grosbach89df9962011-08-26 21:43:41 +00003645 // The "it" instruction has the condition mask on the end of the mnemonic.
3646 if (Mnemonic.startswith("it")) {
3647 ITMask = Mnemonic.slice(2, Mnemonic.size());
3648 Mnemonic = Mnemonic.slice(0, 2);
3649 }
3650
Daniel Dunbar352e1482011-01-11 15:59:50 +00003651 return Mnemonic;
3652}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003653
3654/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3655/// inclusion of carry set or predication code operands.
3656//
3657// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003658void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003659getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003660 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003661 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3662 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003663 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003664 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003665 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003666 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003667 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003668 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003669 Mnemonic == "mla" || Mnemonic == "smlal" ||
3670 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003671 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003672 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003673 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003674
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003675 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3676 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3677 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3678 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003679 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3680 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003681 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003682 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3683 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3684 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003685 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3686 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003687 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003688 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003689 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003690 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003691
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003692 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003693 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003694 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003695 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003696 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003697}
3698
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003699bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3700 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003701 // FIXME: This is all horribly hacky. We really need a better way to deal
3702 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003703
3704 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3705 // another does not. Specifically, the MOVW instruction does not. So we
3706 // special case it here and remove the defaulted (non-setting) cc_out
3707 // operand if that's the instruction we're trying to match.
3708 //
3709 // We do this as post-processing of the explicit operands rather than just
3710 // conditionally adding the cc_out in the first place because we need
3711 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003712 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003713 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3714 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3715 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3716 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003717
3718 // Register-register 'add' for thumb does not have a cc_out operand
3719 // when there are only two register operands.
3720 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3721 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3722 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3723 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3724 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003725 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003726 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3727 // have to check the immediate range here since Thumb2 has a variant
3728 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003729 if (((isThumb() && Mnemonic == "add") ||
3730 (isThumbTwo() && Mnemonic == "sub")) &&
3731 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003732 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3733 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3734 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003735 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3736 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3737 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003738 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003739 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3740 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003741 // selecting via the generic "add" mnemonic, so to know that we
3742 // should remove the cc_out operand, we have to explicitly check that
3743 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003744 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3745 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003746 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3747 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3748 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3749 // Nest conditions rather than one big 'if' statement for readability.
3750 //
3751 // If either register is a high reg, it's either one of the SP
3752 // variants (handled above) or a 32-bit encoding, so we just
3753 // check against T3.
3754 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3755 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3756 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3757 return false;
3758 // If both registers are low, we're in an IT block, and the immediate is
3759 // in range, we should use encoding T1 instead, which has a cc_out.
3760 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003761 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003762 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3763 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3764 return false;
3765
3766 // Otherwise, we use encoding T4, which does not have a cc_out
3767 // operand.
3768 return true;
3769 }
3770
Jim Grosbach64944f42011-09-14 21:00:40 +00003771 // The thumb2 multiply instruction doesn't have a CCOut register, so
3772 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3773 // use the 16-bit encoding or not.
3774 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3775 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3776 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3777 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3778 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3779 // If the registers aren't low regs, the destination reg isn't the
3780 // same as one of the source regs, or the cc_out operand is zero
3781 // outside of an IT block, we have to use the 32-bit encoding, so
3782 // remove the cc_out operand.
3783 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3784 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3785 !inITBlock() ||
3786 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3787 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3788 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3789 static_cast<ARMOperand*>(Operands[4])->getReg())))
3790 return true;
3791
3792
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003793
Jim Grosbachf69c8042011-08-24 21:42:27 +00003794 // Register-register 'add/sub' for thumb does not have a cc_out operand
3795 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3796 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3797 // right, this will result in better diagnostics (which operand is off)
3798 // anyway.
3799 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3800 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003801 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3802 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3803 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3804 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003805
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003806 return false;
3807}
3808
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003809/// Parse an arm instruction mnemonic followed by its operands.
3810bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3811 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3812 // Create the leading tokens for the mnemonic, split by '.' characters.
3813 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003814 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003815
Daniel Dunbar352e1482011-01-11 15:59:50 +00003816 // Split out the predication code and carry setting flag from the mnemonic.
3817 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003818 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003819 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003820 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003821 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003822 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003823
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003824 // In Thumb1, only the branch (B) instruction can be predicated.
3825 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3826 Parser.EatToEndOfStatement();
3827 return Error(NameLoc, "conditional execution not supported in Thumb1");
3828 }
3829
Jim Grosbachffa32252011-07-19 19:13:28 +00003830 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3831
Jim Grosbach89df9962011-08-26 21:43:41 +00003832 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3833 // is the mask as it will be for the IT encoding if the conditional
3834 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3835 // where the conditional bit0 is zero, the instruction post-processing
3836 // will adjust the mask accordingly.
3837 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003838 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3839 if (ITMask.size() > 3) {
3840 Parser.EatToEndOfStatement();
3841 return Error(Loc, "too many conditions on IT instruction");
3842 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003843 unsigned Mask = 8;
3844 for (unsigned i = ITMask.size(); i != 0; --i) {
3845 char pos = ITMask[i - 1];
3846 if (pos != 't' && pos != 'e') {
3847 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003848 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00003849 }
3850 Mask >>= 1;
3851 if (ITMask[i - 1] == 't')
3852 Mask |= 8;
3853 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003854 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00003855 }
3856
Jim Grosbachffa32252011-07-19 19:13:28 +00003857 // FIXME: This is all a pretty gross hack. We should automatically handle
3858 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00003859
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003860 // Next, add the CCOut and ConditionCode operands, if needed.
3861 //
3862 // For mnemonics which can ever incorporate a carry setting bit or predication
3863 // code, our matching model involves us always generating CCOut and
3864 // ConditionCode operands to match the mnemonic "as written" and then we let
3865 // the matcher deal with finding the right instruction or generating an
3866 // appropriate error.
3867 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003868 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003869
Jim Grosbach33c16a22011-07-14 22:04:21 +00003870 // If we had a carry-set on an instruction that can't do that, issue an
3871 // error.
3872 if (!CanAcceptCarrySet && CarrySetting) {
3873 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00003874 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00003875 "' can not set flags, but 's' suffix specified");
3876 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003877 // If we had a predication code on an instruction that can't do that, issue an
3878 // error.
3879 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3880 Parser.EatToEndOfStatement();
3881 return Error(NameLoc, "instruction '" + Mnemonic +
3882 "' is not predicable, but condition code specified");
3883 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00003884
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003885 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003886 if (CanAcceptCarrySet) {
3887 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003888 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003889 Loc));
3890 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003891
3892 // Add the predication code operand, if necessary.
3893 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003894 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3895 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003896 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003897 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003898 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003899
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003900 // Add the processor imod operand, if necessary.
3901 if (ProcessorIMod) {
3902 Operands.push_back(ARMOperand::CreateImm(
3903 MCConstantExpr::Create(ProcessorIMod, getContext()),
3904 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003905 }
3906
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003907 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00003908 while (Next != StringRef::npos) {
3909 Start = Next;
3910 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003911 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003912
Jim Grosbach4d23e992011-08-24 22:19:48 +00003913 // For now, we're only parsing Thumb1 (for the most part), so
3914 // just ignore ".n" qualifiers. We'll use them to restrict
3915 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00003916 if (ExtraToken != ".n") {
3917 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3918 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3919 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00003920 }
3921
3922 // Read the remaining operands.
3923 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003924 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003925 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003926 Parser.EatToEndOfStatement();
3927 return true;
3928 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003929
3930 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00003931 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003932
3933 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003934 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003935 Parser.EatToEndOfStatement();
3936 return true;
3937 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003938 }
3939 }
Jim Grosbach16c74252010-10-29 14:46:02 +00003940
Chris Lattnercbf8a982010-09-11 16:18:25 +00003941 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00003942 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00003943 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00003944 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00003945 }
Bill Wendling146018f2010-11-06 21:42:12 +00003946
Chris Lattner34e53142010-09-08 05:10:46 +00003947 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00003948
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003949 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3950 // do and don't have a cc_out optional-def operand. With some spot-checks
3951 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003952 // parse and adjust accordingly before actually matching. We shouldn't ever
3953 // try to remove a cc_out operand that was explicitly set on the the
3954 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3955 // table driven matcher doesn't fit well with the ARM instruction set.
3956 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00003957 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3958 Operands.erase(Operands.begin() + 1);
3959 delete Op;
3960 }
3961
Jim Grosbachcf121c32011-07-28 21:57:55 +00003962 // ARM mode 'blx' need special handling, as the register operand version
3963 // is predicable, but the label operand version is not. So, we can't rely
3964 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00003965 // a k_CondCode operand in the list. If we're trying to match the label
3966 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00003967 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3968 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3969 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3970 Operands.erase(Operands.begin() + 1);
3971 delete Op;
3972 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00003973
3974 // The vector-compare-to-zero instructions have a literal token "#0" at
3975 // the end that comes to here as an immediate operand. Convert it to a
3976 // token to play nicely with the matcher.
3977 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3978 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3979 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3980 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3981 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3982 if (CE && CE->getValue() == 0) {
3983 Operands.erase(Operands.begin() + 5);
3984 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3985 delete Op;
3986 }
3987 }
Jim Grosbach68259142011-10-03 22:30:24 +00003988 // VCMP{E} does the same thing, but with a different operand count.
3989 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3990 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3991 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3992 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3993 if (CE && CE->getValue() == 0) {
3994 Operands.erase(Operands.begin() + 4);
3995 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3996 delete Op;
3997 }
3998 }
Jim Grosbach934755a2011-08-22 23:47:13 +00003999 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4000 // end. Convert it to a token here.
4001 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4002 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4003 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4004 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4005 if (CE && CE->getValue() == 0) {
4006 Operands.erase(Operands.begin() + 5);
4007 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4008 delete Op;
4009 }
4010 }
4011
Chris Lattner98986712010-01-14 22:21:20 +00004012 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004013}
4014
Jim Grosbach189610f2011-07-26 18:25:39 +00004015// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004016
4017// return 'true' if register list contains non-low GPR registers,
4018// 'false' otherwise. If Reg is in the register list or is HiReg, set
4019// 'containsReg' to true.
4020static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4021 unsigned HiReg, bool &containsReg) {
4022 containsReg = false;
4023 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4024 unsigned OpReg = Inst.getOperand(i).getReg();
4025 if (OpReg == Reg)
4026 containsReg = true;
4027 // Anything other than a low register isn't legal here.
4028 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4029 return true;
4030 }
4031 return false;
4032}
4033
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004034// Check if the specified regisgter is in the register list of the inst,
4035// starting at the indicated operand number.
4036static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4037 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4038 unsigned OpReg = Inst.getOperand(i).getReg();
4039 if (OpReg == Reg)
4040 return true;
4041 }
4042 return false;
4043}
4044
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004045// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4046// the ARMInsts array) instead. Getting that here requires awkward
4047// API changes, though. Better way?
4048namespace llvm {
4049extern MCInstrDesc ARMInsts[];
4050}
4051static MCInstrDesc &getInstDesc(unsigned Opcode) {
4052 return ARMInsts[Opcode];
4053}
4054
Jim Grosbach189610f2011-07-26 18:25:39 +00004055// FIXME: We would really like to be able to tablegen'erate this.
4056bool ARMAsmParser::
4057validateInstruction(MCInst &Inst,
4058 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004059 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
4060 SMLoc Loc = Operands[0]->getStartLoc();
4061 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004062 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4063 // being allowed in IT blocks, but not being predicable. It just always
4064 // executes.
4065 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004066 unsigned bit = 1;
4067 if (ITState.FirstCond)
4068 ITState.FirstCond = false;
4069 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004070 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004071 // The instruction must be predicable.
4072 if (!MCID.isPredicable())
4073 return Error(Loc, "instructions in IT block must be predicable");
4074 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4075 unsigned ITCond = bit ? ITState.Cond :
4076 ARMCC::getOppositeCondition(ITState.Cond);
4077 if (Cond != ITCond) {
4078 // Find the condition code Operand to get its SMLoc information.
4079 SMLoc CondLoc;
4080 for (unsigned i = 1; i < Operands.size(); ++i)
4081 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4082 CondLoc = Operands[i]->getStartLoc();
4083 return Error(CondLoc, "incorrect condition in IT block; got '" +
4084 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4085 "', but expected '" +
4086 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4087 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004088 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004089 } else if (isThumbTwo() && MCID.isPredicable() &&
4090 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004091 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4092 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004093 return Error(Loc, "predicated instructions must be in IT block");
4094
Jim Grosbach189610f2011-07-26 18:25:39 +00004095 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004096 case ARM::LDRD:
4097 case ARM::LDRD_PRE:
4098 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004099 case ARM::LDREXD: {
4100 // Rt2 must be Rt + 1.
4101 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4102 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4103 if (Rt2 != Rt + 1)
4104 return Error(Operands[3]->getStartLoc(),
4105 "destination operands must be sequential");
4106 return false;
4107 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004108 case ARM::STRD: {
4109 // Rt2 must be Rt + 1.
4110 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4111 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4112 if (Rt2 != Rt + 1)
4113 return Error(Operands[3]->getStartLoc(),
4114 "source operands must be sequential");
4115 return false;
4116 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004117 case ARM::STRD_PRE:
4118 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004119 case ARM::STREXD: {
4120 // Rt2 must be Rt + 1.
4121 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4122 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4123 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004124 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004125 "source operands must be sequential");
4126 return false;
4127 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004128 case ARM::SBFX:
4129 case ARM::UBFX: {
4130 // width must be in range [1, 32-lsb]
4131 unsigned lsb = Inst.getOperand(2).getImm();
4132 unsigned widthm1 = Inst.getOperand(3).getImm();
4133 if (widthm1 >= 32 - lsb)
4134 return Error(Operands[5]->getStartLoc(),
4135 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004136 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004137 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004138 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004139 // If we're parsing Thumb2, the .w variant is available and handles
4140 // most cases that are normally illegal for a Thumb1 LDM
4141 // instruction. We'll make the transformation in processInstruction()
4142 // if necessary.
4143 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004144 // Thumb LDM instructions are writeback iff the base register is not
4145 // in the register list.
4146 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004147 bool hasWritebackToken =
4148 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4149 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004150 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004151 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004152 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4153 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004154 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004155 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004156 return Error(Operands[2]->getStartLoc(),
4157 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004158 // If we should not have writeback, there must not be a '!'. This is
4159 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004160 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004161 return Error(Operands[3]->getStartLoc(),
4162 "writeback operator '!' not allowed when base register "
4163 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004164
4165 break;
4166 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004167 case ARM::t2LDMIA_UPD: {
4168 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4169 return Error(Operands[4]->getStartLoc(),
4170 "writeback operator '!' not allowed when base register "
4171 "in register list");
4172 break;
4173 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004174 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004175 bool listContainsBase;
4176 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4177 return Error(Operands[2]->getStartLoc(),
4178 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004179 break;
4180 }
4181 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004182 bool listContainsBase;
4183 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4184 return Error(Operands[2]->getStartLoc(),
4185 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004186 break;
4187 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004188 case ARM::tSTMIA_UPD: {
4189 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004190 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004191 return Error(Operands[4]->getStartLoc(),
4192 "registers must be in range r0-r7");
4193 break;
4194 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004195 }
4196
4197 return false;
4198}
4199
Jim Grosbachf8fce712011-08-11 17:35:48 +00004200void ARMAsmParser::
4201processInstruction(MCInst &Inst,
4202 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4203 switch (Inst.getOpcode()) {
4204 case ARM::LDMIA_UPD:
4205 // If this is a load of a single register via a 'pop', then we should use
4206 // a post-indexed LDR instruction instead, per the ARM ARM.
4207 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4208 Inst.getNumOperands() == 5) {
4209 MCInst TmpInst;
4210 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4211 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4212 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4213 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4214 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4215 TmpInst.addOperand(MCOperand::CreateImm(4));
4216 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4217 TmpInst.addOperand(Inst.getOperand(3));
4218 Inst = TmpInst;
4219 }
4220 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004221 case ARM::STMDB_UPD:
4222 // If this is a store of a single register via a 'push', then we should use
4223 // a pre-indexed STR instruction instead, per the ARM ARM.
4224 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4225 Inst.getNumOperands() == 5) {
4226 MCInst TmpInst;
4227 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4228 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4229 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4230 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4231 TmpInst.addOperand(MCOperand::CreateImm(-4));
4232 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4233 TmpInst.addOperand(Inst.getOperand(3));
4234 Inst = TmpInst;
4235 }
4236 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004237 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004238 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4239 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4240 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4241 // to encoding T1 if <Rd> is omitted."
4242 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004243 Inst.setOpcode(ARM::tADDi3);
4244 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004245 case ARM::tSUBi8:
4246 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4247 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4248 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4249 // to encoding T1 if <Rd> is omitted."
4250 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4251 Inst.setOpcode(ARM::tSUBi3);
4252 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004253 case ARM::tB:
4254 // A Thumb conditional branch outside of an IT block is a tBcc.
4255 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4256 Inst.setOpcode(ARM::tBcc);
4257 break;
4258 case ARM::t2B:
4259 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4260 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4261 Inst.setOpcode(ARM::t2Bcc);
4262 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004263 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004264 // If the conditional is AL or we're in an IT block, we really want t2B.
4265 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004266 Inst.setOpcode(ARM::t2B);
4267 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004268 case ARM::tBcc:
4269 // If the conditional is AL, we really want tB.
4270 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4271 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004272 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004273 case ARM::tLDMIA: {
4274 // If the register list contains any high registers, or if the writeback
4275 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4276 // instead if we're in Thumb2. Otherwise, this should have generated
4277 // an error in validateInstruction().
4278 unsigned Rn = Inst.getOperand(0).getReg();
4279 bool hasWritebackToken =
4280 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4281 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4282 bool listContainsBase;
4283 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4284 (!listContainsBase && !hasWritebackToken) ||
4285 (listContainsBase && hasWritebackToken)) {
4286 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4287 assert (isThumbTwo());
4288 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4289 // If we're switching to the updating version, we need to insert
4290 // the writeback tied operand.
4291 if (hasWritebackToken)
4292 Inst.insert(Inst.begin(),
4293 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4294 }
4295 break;
4296 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004297 case ARM::tSTMIA_UPD: {
4298 // If the register list contains any high registers, we need to use
4299 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4300 // should have generated an error in validateInstruction().
4301 unsigned Rn = Inst.getOperand(0).getReg();
4302 bool listContainsBase;
4303 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4304 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4305 assert (isThumbTwo());
4306 Inst.setOpcode(ARM::t2STMIA_UPD);
4307 }
4308 break;
4309 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004310 case ARM::t2MOVi: {
4311 // If we can use the 16-bit encoding and the user didn't explicitly
4312 // request the 32-bit variant, transform it here.
4313 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4314 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004315 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4316 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4317 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004318 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4319 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4320 // The operands aren't in the same order for tMOVi8...
4321 MCInst TmpInst;
4322 TmpInst.setOpcode(ARM::tMOVi8);
4323 TmpInst.addOperand(Inst.getOperand(0));
4324 TmpInst.addOperand(Inst.getOperand(4));
4325 TmpInst.addOperand(Inst.getOperand(1));
4326 TmpInst.addOperand(Inst.getOperand(2));
4327 TmpInst.addOperand(Inst.getOperand(3));
4328 Inst = TmpInst;
4329 }
4330 break;
4331 }
4332 case ARM::t2MOVr: {
4333 // If we can use the 16-bit encoding and the user didn't explicitly
4334 // request the 32-bit variant, transform it here.
4335 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4336 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4337 Inst.getOperand(2).getImm() == ARMCC::AL &&
4338 Inst.getOperand(4).getReg() == ARM::CPSR &&
4339 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4340 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4341 // The operands aren't the same for tMOV[S]r... (no cc_out)
4342 MCInst TmpInst;
4343 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4344 TmpInst.addOperand(Inst.getOperand(0));
4345 TmpInst.addOperand(Inst.getOperand(1));
4346 TmpInst.addOperand(Inst.getOperand(2));
4347 TmpInst.addOperand(Inst.getOperand(3));
4348 Inst = TmpInst;
4349 }
4350 break;
4351 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004352 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004353 case ARM::t2SXTB:
4354 case ARM::t2UXTH:
4355 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004356 // If we can use the 16-bit encoding and the user didn't explicitly
4357 // request the 32-bit variant, transform it here.
4358 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4359 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4360 Inst.getOperand(2).getImm() == 0 &&
4361 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4362 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004363 unsigned NewOpc;
4364 switch (Inst.getOpcode()) {
4365 default: llvm_unreachable("Illegal opcode!");
4366 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4367 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4368 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4369 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4370 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004371 // The operands aren't the same for thumb1 (no rotate operand).
4372 MCInst TmpInst;
4373 TmpInst.setOpcode(NewOpc);
4374 TmpInst.addOperand(Inst.getOperand(0));
4375 TmpInst.addOperand(Inst.getOperand(1));
4376 TmpInst.addOperand(Inst.getOperand(3));
4377 TmpInst.addOperand(Inst.getOperand(4));
4378 Inst = TmpInst;
4379 }
4380 break;
4381 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004382 case ARM::t2IT: {
4383 // The mask bits for all but the first condition are represented as
4384 // the low bit of the condition code value implies 't'. We currently
4385 // always have 1 implies 't', so XOR toggle the bits if the low bit
4386 // of the condition code is zero. The encoding also expects the low
4387 // bit of the condition to be encoded as bit 4 of the mask operand,
4388 // so mask that in if needed
4389 MCOperand &MO = Inst.getOperand(1);
4390 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004391 unsigned OrigMask = Mask;
4392 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004393 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004394 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4395 for (unsigned i = 3; i != TZ; --i)
4396 Mask ^= 1 << i;
4397 } else
4398 Mask |= 0x10;
4399 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004400
4401 // Set up the IT block state according to the IT instruction we just
4402 // matched.
4403 assert(!inITBlock() && "nested IT blocks?!");
4404 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4405 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4406 ITState.CurPosition = 0;
4407 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004408 break;
4409 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004410 }
4411}
4412
Jim Grosbach47a0d522011-08-16 20:45:50 +00004413unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4414 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4415 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004416 unsigned Opc = Inst.getOpcode();
4417 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004418 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4419 assert(MCID.hasOptionalDef() &&
4420 "optionally flag setting instruction missing optional def operand");
4421 assert(MCID.NumOperands == Inst.getNumOperands() &&
4422 "operand count mismatch!");
4423 // Find the optional-def operand (cc_out).
4424 unsigned OpNo;
4425 for (OpNo = 0;
4426 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4427 ++OpNo)
4428 ;
4429 // If we're parsing Thumb1, reject it completely.
4430 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4431 return Match_MnemonicFail;
4432 // If we're parsing Thumb2, which form is legal depends on whether we're
4433 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004434 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4435 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004436 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004437 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4438 inITBlock())
4439 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004440 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004441 // Some high-register supporting Thumb1 encodings only allow both registers
4442 // to be from r0-r7 when in Thumb2.
4443 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4444 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4445 isARMLowRegister(Inst.getOperand(2).getReg()))
4446 return Match_RequiresThumb2;
4447 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004448 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004449 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4450 isARMLowRegister(Inst.getOperand(1).getReg()))
4451 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004452 return Match_Success;
4453}
4454
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004455bool ARMAsmParser::
4456MatchAndEmitInstruction(SMLoc IDLoc,
4457 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4458 MCStreamer &Out) {
4459 MCInst Inst;
4460 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004461 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004462 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004463 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004464 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004465 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004466 // Context sensitive operand constraints aren't handled by the matcher,
4467 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004468 if (validateInstruction(Inst, Operands)) {
4469 // Still progress the IT block, otherwise one wrong condition causes
4470 // nasty cascading errors.
4471 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004472 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004473 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004474
Jim Grosbachf8fce712011-08-11 17:35:48 +00004475 // Some instructions need post-processing to, for example, tweak which
4476 // encoding is selected.
4477 processInstruction(Inst, Operands);
4478
Jim Grosbacha1109882011-09-02 23:22:08 +00004479 // Only move forward at the very end so that everything in validate
4480 // and process gets a consistent answer about whether we're in an IT
4481 // block.
4482 forwardITPosition();
4483
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004484 Out.EmitInstruction(Inst);
4485 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004486 case Match_MissingFeature:
4487 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4488 return true;
4489 case Match_InvalidOperand: {
4490 SMLoc ErrorLoc = IDLoc;
4491 if (ErrorInfo != ~0U) {
4492 if (ErrorInfo >= Operands.size())
4493 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004494
Chris Lattnere73d4f82010-10-28 21:41:58 +00004495 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4496 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4497 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004498
Chris Lattnere73d4f82010-10-28 21:41:58 +00004499 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004500 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004501 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004502 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004503 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004504 // The converter function will have already emited a diagnostic.
4505 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004506 case Match_RequiresNotITBlock:
4507 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004508 case Match_RequiresITBlock:
4509 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004510 case Match_RequiresV6:
4511 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4512 case Match_RequiresThumb2:
4513 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004514 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004515
Eric Christopherc223e2b2010-10-29 09:26:59 +00004516 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004517 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004518}
4519
Jim Grosbach1355cf12011-07-26 17:10:22 +00004520/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004521bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4522 StringRef IDVal = DirectiveID.getIdentifier();
4523 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004524 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004525 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004526 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004527 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004528 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004529 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004530 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004531 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004532 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004533 return true;
4534}
4535
Jim Grosbach1355cf12011-07-26 17:10:22 +00004536/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004537/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004538bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004539 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4540 for (;;) {
4541 const MCExpr *Value;
4542 if (getParser().ParseExpression(Value))
4543 return true;
4544
Chris Lattneraaec2052010-01-19 19:46:13 +00004545 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004546
4547 if (getLexer().is(AsmToken::EndOfStatement))
4548 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004549
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004550 // FIXME: Improve diagnostic.
4551 if (getLexer().isNot(AsmToken::Comma))
4552 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004553 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004554 }
4555 }
4556
Sean Callananb9a25b72010-01-19 20:27:46 +00004557 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004558 return false;
4559}
4560
Jim Grosbach1355cf12011-07-26 17:10:22 +00004561/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004562/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004563bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004564 if (getLexer().isNot(AsmToken::EndOfStatement))
4565 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004566 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004567
4568 // TODO: set thumb mode
4569 // TODO: tell the MC streamer the mode
4570 // getParser().getStreamer().Emit???();
4571 return false;
4572}
4573
Jim Grosbach1355cf12011-07-26 17:10:22 +00004574/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004575/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004576bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004577 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4578 bool isMachO = MAI.hasSubsectionsViaSymbols();
4579 StringRef Name;
4580
4581 // Darwin asm has function name after .thumb_func direction
4582 // ELF doesn't
4583 if (isMachO) {
4584 const AsmToken &Tok = Parser.getTok();
4585 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4586 return Error(L, "unexpected token in .thumb_func directive");
4587 Name = Tok.getString();
4588 Parser.Lex(); // Consume the identifier token.
4589 }
4590
Kevin Enderby515d5092009-10-15 20:48:48 +00004591 if (getLexer().isNot(AsmToken::EndOfStatement))
4592 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004593 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004594
Rafael Espindola64695402011-05-16 16:17:21 +00004595 // FIXME: assuming function name will be the line following .thumb_func
4596 if (!isMachO) {
4597 Name = Parser.getTok().getString();
4598 }
4599
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004600 // Mark symbol as a thumb symbol.
4601 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4602 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004603 return false;
4604}
4605
Jim Grosbach1355cf12011-07-26 17:10:22 +00004606/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004607/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004608bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004609 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004610 if (Tok.isNot(AsmToken::Identifier))
4611 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004612 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004613 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004614 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004615 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004616 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004617 else
4618 return Error(L, "unrecognized syntax mode in .syntax directive");
4619
4620 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004621 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004622 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004623
4624 // TODO tell the MC streamer the mode
4625 // getParser().getStreamer().Emit???();
4626 return false;
4627}
4628
Jim Grosbach1355cf12011-07-26 17:10:22 +00004629/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004630/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004631bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004632 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004633 if (Tok.isNot(AsmToken::Integer))
4634 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004635 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004636 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004637 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004638 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004639 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004640 else
4641 return Error(L, "invalid operand to .code directive");
4642
4643 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004644 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004645 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004646
Evan Cheng32869202011-07-08 22:36:29 +00004647 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004648 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004649 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004650 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004651 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004652 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004653 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004654 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004655 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004656
Kevin Enderby515d5092009-10-15 20:48:48 +00004657 return false;
4658}
4659
Sean Callanan90b70972010-04-07 20:29:34 +00004660extern "C" void LLVMInitializeARMAsmLexer();
4661
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004662/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004663extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004664 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4665 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004666 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004667}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004668
Chris Lattner0692ee62010-09-06 19:11:01 +00004669#define GET_REGISTER_MATCHER
4670#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004671#include "ARMGenAsmMatcher.inc"