blob: ad5f061eabae6931b44ba0224daca0255b6c98fb [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Owen Anderson0c9f2502011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000036
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattner3a697562010-10-28 17:20:03 +000039namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000042
Evan Cheng94b95502011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000047 struct {
48 ARMCC::CondCodes Cond; // Condition for IT block.
49 unsigned Mask:4; // Condition mask for instructions.
50 // Starting at first 1 (from lsb).
51 // '1' condition as indicated in IT.
52 // '0' inverse of condition (else).
53 // Count of instructions in IT block is
54 // 4 - trailingzeroes(mask)
55
56 bool FirstCond; // Explicit flag for when we're parsing the
57 // First instruction in the IT block. It's
58 // implied in the mask, so needs special
59 // handling.
60
61 unsigned CurPosition; // Current position in parsing of IT
62 // block. In range [0,3]. Initialized
63 // according to count of instructions in block.
64 // ~0U if no active IT block.
65 } ITState;
66 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000067 void forwardITPosition() {
68 if (!inITBlock()) return;
69 // Move to the next instruction in the IT block, if there is one. If not,
70 // mark the block as done.
71 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
72 if (++ITState.CurPosition == 5 - TZ)
73 ITState.CurPosition = ~0U; // Done with the IT block after this.
74 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000075
76
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000078 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
79
80 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbach1355cf12011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseDirectiveWord(unsigned Size, SMLoc L);
93 bool parseDirectiveThumb(SMLoc L);
94 bool parseDirectiveThumbFunc(SMLoc L);
95 bool parseDirectiveCode(SMLoc L);
96 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000097
Jim Grosbach1355cf12011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000103
Evan Chengebdeeab2011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloyacad68d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng32869202011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000123 }
James Molloyacad68d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000127
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000130
Chris Lattner0692ee62010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach89df9962011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000141 OperandMatchResultTy parseCoprocOptionOperand(
142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000143 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000149 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
150 StringRef Op, int Low, int High);
151 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
152 return parsePKHImm(O, "lsl", 0, 31);
153 }
154 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
155 return parsePKHImm(O, "asr", 1, 32);
156 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000157 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000158 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000159 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000160 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000161 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000162 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000163 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000164 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000165
166 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000167 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
168 const SmallVectorImpl<MCParsedAsmOperand*> &);
169 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
170 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000171 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
172 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000173 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
174 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000175 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000176 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000177 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000179 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000181 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000183 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000185 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
187 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
189 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
191 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000193 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000195 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000197 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000199 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000201 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
203 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000205
206 bool validateInstruction(MCInst &Inst,
207 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000208 void processInstruction(MCInst &Inst,
209 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000210 bool shouldOmitCCOutOperand(StringRef Mnemonic,
211 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000212
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000213public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000214 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000215 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000216 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000217 Match_RequiresV6,
218 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000219 };
220
Evan Chengffc0e732011-07-09 05:47:46 +0000221 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000222 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000223 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000224
Evan Chengebdeeab2011-07-08 01:53:10 +0000225 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000226 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000227
228 // Not in an ITBlock to start with.
229 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000230 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000231
Jim Grosbach1355cf12011-07-26 17:10:22 +0000232 // Implementation of the MCTargetAsmParser interface:
233 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
234 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000235 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000236 bool ParseDirective(AsmToken DirectiveID);
237
Jim Grosbach47a0d522011-08-16 20:45:50 +0000238 unsigned checkTargetMatchPredicate(MCInst &Inst);
239
Jim Grosbach1355cf12011-07-26 17:10:22 +0000240 bool MatchAndEmitInstruction(SMLoc IDLoc,
241 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
242 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000243};
Jim Grosbach16c74252010-10-29 14:46:02 +0000244} // end anonymous namespace
245
Chris Lattner3a697562010-10-28 17:20:03 +0000246namespace {
247
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000248/// ARMOperand - Instances of this class represent a parsed ARM machine
249/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000250class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000251 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000252 k_CondCode,
253 k_CCOut,
254 k_ITCondMask,
255 k_CoprocNum,
256 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000257 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000258 k_Immediate,
259 k_FPImmediate,
260 k_MemBarrierOpt,
261 k_Memory,
262 k_PostIndexRegister,
263 k_MSRMask,
264 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000265 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_Register,
267 k_RegisterList,
268 k_DPRRegisterList,
269 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000270 k_VectorList,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000271 k_ShiftedRegister,
272 k_ShiftedImmediate,
273 k_ShifterImmediate,
274 k_RotateImmediate,
275 k_BitfieldDescriptor,
276 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000277 } Kind;
278
Sean Callanan76264762010-04-02 22:27:05 +0000279 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000280 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000281
282 union {
283 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000284 ARMCC::CondCodes Val;
285 } CC;
286
287 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000288 unsigned Val;
289 } Cop;
290
291 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000292 unsigned Val;
293 } CoprocOption;
294
295 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000296 unsigned Mask:4;
297 } ITMask;
298
299 struct {
300 ARM_MB::MemBOpt Val;
301 } MBOpt;
302
303 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000304 ARM_PROC::IFlags Val;
305 } IFlags;
306
307 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000308 unsigned Val;
309 } MMask;
310
311 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000312 const char *Data;
313 unsigned Length;
314 } Tok;
315
316 struct {
317 unsigned RegNum;
318 } Reg;
319
Jim Grosbach862019c2011-10-18 23:02:30 +0000320 // A vector register list is a sequential list of 1 to 4 registers.
321 struct {
322 unsigned RegNum;
323 unsigned Count;
324 } VectorList;
325
Bill Wendling8155e5b2010-11-06 22:19:43 +0000326 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000327 unsigned Val;
328 } VectorIndex;
329
330 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000331 const MCExpr *Val;
332 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000333
Jim Grosbach9d390362011-10-03 23:38:36 +0000334 struct {
335 unsigned Val; // encoded 8-bit representation
336 } FPImm;
337
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000338 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000339 struct {
340 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000341 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
342 // was specified.
343 const MCConstantExpr *OffsetImm; // Offset immediate value
344 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
345 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000346 unsigned ShiftImm; // shift for OffsetReg.
347 unsigned Alignment; // 0 = no alignment specified
348 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000349 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000350 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000351
352 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000353 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000354 bool isAdd;
355 ARM_AM::ShiftOpc ShiftTy;
356 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000357 } PostIdxReg;
358
359 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000360 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000361 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000362 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000363 struct {
364 ARM_AM::ShiftOpc ShiftTy;
365 unsigned SrcReg;
366 unsigned ShiftReg;
367 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000368 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000369 struct {
370 ARM_AM::ShiftOpc ShiftTy;
371 unsigned SrcReg;
372 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000373 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000374 struct {
375 unsigned Imm;
376 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000377 struct {
378 unsigned LSB;
379 unsigned Width;
380 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000381 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000382
Bill Wendling146018f2010-11-06 21:42:12 +0000383 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
384public:
Sean Callanan76264762010-04-02 22:27:05 +0000385 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
386 Kind = o.Kind;
387 StartLoc = o.StartLoc;
388 EndLoc = o.EndLoc;
389 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000390 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000391 CC = o.CC;
392 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000393 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000394 ITMask = o.ITMask;
395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000397 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000398 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_CCOut:
400 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000401 Reg = o.Reg;
402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_RegisterList:
404 case k_DPRRegisterList:
405 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000406 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000407 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000408 case k_VectorList:
409 VectorList = o.VectorList;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_CoprocNum:
412 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000413 Cop = o.Cop;
414 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000415 case k_CoprocOption:
416 CoprocOption = o.CoprocOption;
417 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000418 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000419 Imm = o.Imm;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000422 FPImm = o.FPImm;
423 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000424 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000425 MBOpt = o.MBOpt;
426 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000427 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000428 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000431 PostIdxReg = o.PostIdxReg;
432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000434 MMask = o.MMask;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000437 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000440 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000443 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000446 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000449 RotImm = o.RotImm;
450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000452 Bitfield = o.Bitfield;
453 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000454 case k_VectorIndex:
455 VectorIndex = o.VectorIndex;
456 break;
Sean Callanan76264762010-04-02 22:27:05 +0000457 }
458 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000459
Sean Callanan76264762010-04-02 22:27:05 +0000460 /// getStartLoc - Get the location of the first token of this operand.
461 SMLoc getStartLoc() const { return StartLoc; }
462 /// getEndLoc - Get the location of the last token of this operand.
463 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000464
Daniel Dunbar8462b302010-08-11 06:36:53 +0000465 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000466 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000467 return CC.Val;
468 }
469
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000470 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000472 return Cop.Val;
473 }
474
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000475 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000476 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000477 return StringRef(Tok.Data, Tok.Length);
478 }
479
480 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000481 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000482 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000483 }
484
Bill Wendling5fa22a12010-11-09 23:28:44 +0000485 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000486 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
487 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000488 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000489 }
490
Kevin Enderbycfe07242009-10-13 22:19:02 +0000491 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000493 return Imm.Val;
494 }
495
Jim Grosbach9d390362011-10-03 23:38:36 +0000496 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000497 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000498 return FPImm.Val;
499 }
500
Jim Grosbach460a9052011-10-07 23:56:00 +0000501 unsigned getVectorIndex() const {
502 assert(Kind == k_VectorIndex && "Invalid access!");
503 return VectorIndex.Val;
504 }
505
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000506 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000507 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000508 return MBOpt.Val;
509 }
510
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000511 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000512 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000513 return IFlags.Val;
514 }
515
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000516 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000517 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000518 return MMask.Val;
519 }
520
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000521 bool isCoprocNum() const { return Kind == k_CoprocNum; }
522 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000523 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 bool isCondCode() const { return Kind == k_CondCode; }
525 bool isCCOut() const { return Kind == k_CCOut; }
526 bool isITMask() const { return Kind == k_ITCondMask; }
527 bool isITCondCode() const { return Kind == k_CondCode; }
528 bool isImm() const { return Kind == k_Immediate; }
529 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000530 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000531 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000532 return false;
533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
534 if (!CE) return false;
535 int64_t Value = CE->getValue();
536 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
537 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000538 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000539 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000540 return false;
541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
542 if (!CE) return false;
543 int64_t Value = CE->getValue();
544 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
545 }
546 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000547 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000548 return false;
549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
550 if (!CE) return false;
551 int64_t Value = CE->getValue();
552 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
553 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000554 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000555 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000556 return false;
557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
558 if (!CE) return false;
559 int64_t Value = CE->getValue();
560 return Value >= 0 && Value < 256;
561 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000562 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000563 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000564 return false;
565 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
566 if (!CE) return false;
567 int64_t Value = CE->getValue();
568 return Value >= 0 && Value < 8;
569 }
570 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000571 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000572 return false;
573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return Value >= 0 && Value < 16;
577 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000578 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000579 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000580 return false;
581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
582 if (!CE) return false;
583 int64_t Value = CE->getValue();
584 return Value >= 0 && Value < 32;
585 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000586 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000587 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000588 return false;
589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
590 if (!CE) return false;
591 int64_t Value = CE->getValue();
592 return Value > 0 && Value < 17;
593 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000594 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000595 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000596 return false;
597 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
598 if (!CE) return false;
599 int64_t Value = CE->getValue();
600 return Value > 0 && Value < 33;
601 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000602 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000603 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000604 return false;
605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
606 if (!CE) return false;
607 int64_t Value = CE->getValue();
608 return Value >= 0 && Value < 65536;
609 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000610 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000611 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000612 return false;
613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
614 // If it's not a constant expression, it'll generate a fixup and be
615 // handled later.
616 if (!CE) return true;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 65536;
619 }
Jim Grosbached838482011-07-26 16:24:27 +0000620 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000621 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000622 return false;
623 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
624 if (!CE) return false;
625 int64_t Value = CE->getValue();
626 return Value >= 0 && Value <= 0xffffff;
627 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000628 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000629 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000630 return false;
631 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
632 if (!CE) return false;
633 int64_t Value = CE->getValue();
634 return Value > 0 && Value < 33;
635 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000636 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000637 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000638 return false;
639 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
640 if (!CE) return false;
641 int64_t Value = CE->getValue();
642 return Value >= 0 && Value < 32;
643 }
644 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000645 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000646 return false;
647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
648 if (!CE) return false;
649 int64_t Value = CE->getValue();
650 return Value > 0 && Value <= 32;
651 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000652 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000653 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000654 return false;
655 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
656 if (!CE) return false;
657 int64_t Value = CE->getValue();
658 return ARM_AM::getSOImmVal(Value) != -1;
659 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000660 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000661 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000662 return false;
663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
664 if (!CE) return false;
665 int64_t Value = CE->getValue();
666 return ARM_AM::getT2SOImmVal(Value) != -1;
667 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000668 bool isT2SOImmNot() const {
669 if (Kind != k_Immediate)
670 return false;
671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return ARM_AM::getT2SOImmVal(~Value) != -1;
675 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000676 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000677 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000678 return false;
679 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
680 if (!CE) return false;
681 int64_t Value = CE->getValue();
682 return Value == 1 || Value == 0;
683 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000684 bool isReg() const { return Kind == k_Register; }
685 bool isRegList() const { return Kind == k_RegisterList; }
686 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
687 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
688 bool isToken() const { return Kind == k_Token; }
689 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
690 bool isMemory() const { return Kind == k_Memory; }
691 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
692 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
693 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
694 bool isRotImm() const { return Kind == k_RotateImmediate; }
695 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
696 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000697 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000698 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000699 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000700 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000701 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000702 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000703 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000704 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
705 (alignOK || Memory.Alignment == 0);
706 }
707 bool isAlignedMemory() const {
708 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000709 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000710 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000711 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000712 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000713 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000714 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000715 if (!Memory.OffsetImm) return true;
716 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000717 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000718 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000719 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000720 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000721 return false;
722 // Immediate offset in range [-4095, 4095].
723 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
724 if (!CE) return false;
725 int64_t Val = CE->getValue();
726 return Val > -4096 && Val < 4096;
727 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000728 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000729 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000730 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000731 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000732 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000733 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000734 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000735 if (!Memory.OffsetImm) return true;
736 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000737 return Val > -256 && Val < 256;
738 }
739 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000740 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000741 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000742 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000743 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
744 // Immediate offset in range [-255, 255].
745 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
746 if (!CE) return false;
747 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000748 // Special case, #-0 is INT32_MIN.
749 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000750 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000751 bool isAddrMode5() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000752 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000753 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000754 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000755 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000756 if (!Memory.OffsetImm) return true;
757 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000758 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
759 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000760 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000761 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000762 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000763 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000764 return false;
765 return true;
766 }
767 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000768 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000769 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
770 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000771 return false;
772 return true;
773 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000774 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000775 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000776 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000777 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000778 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000779 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000780 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
781 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000782 return false;
783 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000784 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000785 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000786 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000787 return false;
788 return true;
789 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000790 bool isMemThumbRR() const {
791 // Thumb reg+reg addressing is simple. Just two registers, a base and
792 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000793 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000794 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000795 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000796 return isARMLowRegister(Memory.BaseRegNum) &&
797 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000798 }
799 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000800 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000801 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000802 return false;
803 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000804 if (!Memory.OffsetImm) return true;
805 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000806 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
807 }
Jim Grosbach38466302011-08-19 18:55:51 +0000808 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000809 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000810 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000811 return false;
812 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000813 if (!Memory.OffsetImm) return true;
814 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000815 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
816 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000817 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000818 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000819 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000820 return false;
821 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000822 if (!Memory.OffsetImm) return true;
823 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000824 return Val >= 0 && Val <= 31;
825 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000826 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000827 if (!isMemory() || Memory.OffsetRegNum != 0 ||
828 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000829 return false;
830 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000831 if (!Memory.OffsetImm) return true;
832 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000833 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000834 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000835 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000836 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000837 return false;
838 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000839 if (!Memory.OffsetImm) return true;
840 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000841 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
842 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000843 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000844 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000845 return false;
846 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000847 if (!Memory.OffsetImm) return true;
848 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000849 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
850 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000851 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000852 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000853 return false;
854 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000857 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000858 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000859 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000861 return false;
862 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000865 return Val >= 0 && Val < 256;
866 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000867 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000869 return false;
870 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000873 return Val > -256 && Val < 0;
874 }
875 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000877 return false;
878 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000881 return (Val >= 0 && Val < 4096);
882 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000883 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000884 // If we have an immediate that's not a constant, treat it as a label
885 // reference needing a fixup. If it is a constant, it's something else
886 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000887 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000888 return true;
889
Jim Grosbach57dcb852011-10-11 17:29:55 +0000890 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000891 return false;
892 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000893 if (!Memory.OffsetImm) return true;
894 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000895 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000896 }
897 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000898 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000899 return false;
900 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
901 if (!CE) return false;
902 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000903 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000904 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000905 bool isPostIdxImm8s4() const {
906 if (Kind != k_Immediate)
907 return false;
908 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
909 if (!CE) return false;
910 int64_t Val = CE->getValue();
911 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
912 (Val == INT32_MIN);
913 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000914
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000915 bool isMSRMask() const { return Kind == k_MSRMask; }
916 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000917
Jim Grosbach0e387b22011-10-17 22:26:03 +0000918 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000919 bool isVecListOneD() const {
920 if (Kind != k_VectorList) return false;
921 return VectorList.Count == 1;
922 }
923
Jim Grosbach280dfad2011-10-21 18:54:25 +0000924 bool isVecListTwoD() const {
925 if (Kind != k_VectorList) return false;
926 return VectorList.Count == 2;
927 }
928
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000929 bool isVecListThreeD() const {
930 if (Kind != k_VectorList) return false;
931 return VectorList.Count == 3;
932 }
933
Jim Grosbachb6310312011-10-21 20:35:01 +0000934 bool isVecListFourD() const {
935 if (Kind != k_VectorList) return false;
936 return VectorList.Count == 4;
937 }
938
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000939 bool isVecListTwoQ() const {
940 if (Kind != k_VectorList) return false;
941 //FIXME: We haven't taught the parser to handle by-two register lists
942 // yet, so don't pretend to know one.
943 return VectorList.Count == 2 && false;
944 }
945
Jim Grosbach460a9052011-10-07 23:56:00 +0000946 bool isVectorIndex8() const {
947 if (Kind != k_VectorIndex) return false;
948 return VectorIndex.Val < 8;
949 }
950 bool isVectorIndex16() const {
951 if (Kind != k_VectorIndex) return false;
952 return VectorIndex.Val < 4;
953 }
954 bool isVectorIndex32() const {
955 if (Kind != k_VectorIndex) return false;
956 return VectorIndex.Val < 2;
957 }
958
Jim Grosbach0e387b22011-10-17 22:26:03 +0000959 bool isNEONi8splat() const {
960 if (Kind != k_Immediate)
961 return false;
962 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
963 // Must be a constant.
964 if (!CE) return false;
965 int64_t Value = CE->getValue();
966 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
967 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000968 return Value >= 0 && Value < 256;
969 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000970
Jim Grosbachea461102011-10-17 23:09:09 +0000971 bool isNEONi16splat() const {
972 if (Kind != k_Immediate)
973 return false;
974 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
975 // Must be a constant.
976 if (!CE) return false;
977 int64_t Value = CE->getValue();
978 // i16 value in the range [0,255] or [0x0100, 0xff00]
979 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
980 }
981
Jim Grosbach6248a542011-10-18 00:22:00 +0000982 bool isNEONi32splat() const {
983 if (Kind != k_Immediate)
984 return false;
985 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
986 // Must be a constant.
987 if (!CE) return false;
988 int64_t Value = CE->getValue();
989 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
990 return (Value >= 0 && Value < 256) ||
991 (Value >= 0x0100 && Value <= 0xff00) ||
992 (Value >= 0x010000 && Value <= 0xff0000) ||
993 (Value >= 0x01000000 && Value <= 0xff000000);
994 }
995
996 bool isNEONi32vmov() const {
997 if (Kind != k_Immediate)
998 return false;
999 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1000 // Must be a constant.
1001 if (!CE) return false;
1002 int64_t Value = CE->getValue();
1003 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1004 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1005 return (Value >= 0 && Value < 256) ||
1006 (Value >= 0x0100 && Value <= 0xff00) ||
1007 (Value >= 0x010000 && Value <= 0xff0000) ||
1008 (Value >= 0x01000000 && Value <= 0xff000000) ||
1009 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1010 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1011 }
1012
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001013 bool isNEONi64splat() const {
1014 if (Kind != k_Immediate)
1015 return false;
1016 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1017 // Must be a constant.
1018 if (!CE) return false;
1019 uint64_t Value = CE->getValue();
1020 // i64 value with each byte being either 0 or 0xff.
1021 for (unsigned i = 0; i < 8; ++i)
1022 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1023 return true;
1024 }
1025
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001026 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001027 // Add as immediates when possible. Null MCExpr = 0.
1028 if (Expr == 0)
1029 Inst.addOperand(MCOperand::CreateImm(0));
1030 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001031 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1032 else
1033 Inst.addOperand(MCOperand::CreateExpr(Expr));
1034 }
1035
Daniel Dunbar8462b302010-08-11 06:36:53 +00001036 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001037 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001038 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001039 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1040 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001041 }
1042
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001043 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1044 assert(N == 1 && "Invalid number of operands!");
1045 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1046 }
1047
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001048 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1049 assert(N == 1 && "Invalid number of operands!");
1050 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1051 }
1052
1053 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1054 assert(N == 1 && "Invalid number of operands!");
1055 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1056 }
1057
Jim Grosbach89df9962011-08-26 21:43:41 +00001058 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1059 assert(N == 1 && "Invalid number of operands!");
1060 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1061 }
1062
1063 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1064 assert(N == 1 && "Invalid number of operands!");
1065 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1066 }
1067
Jim Grosbachd67641b2010-12-06 18:21:12 +00001068 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1069 assert(N == 1 && "Invalid number of operands!");
1070 Inst.addOperand(MCOperand::CreateReg(getReg()));
1071 }
1072
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001073 void addRegOperands(MCInst &Inst, unsigned N) const {
1074 assert(N == 1 && "Invalid number of operands!");
1075 Inst.addOperand(MCOperand::CreateReg(getReg()));
1076 }
1077
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001078 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001079 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001080 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1081 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1082 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001083 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001084 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001085 }
1086
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001087 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001088 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001089 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1090 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001091 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001092 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001093 }
1094
Jim Grosbach580f4a92011-07-25 22:20:28 +00001095 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001096 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001097 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1098 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001099 }
1100
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001101 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001102 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001103 const SmallVectorImpl<unsigned> &RegList = getRegList();
1104 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001105 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1106 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001107 }
1108
Bill Wendling0f630752010-11-17 04:32:08 +00001109 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1110 addRegListOperands(Inst, N);
1111 }
1112
1113 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1114 addRegListOperands(Inst, N);
1115 }
1116
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001117 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
1119 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1120 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1121 }
1122
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001123 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1124 assert(N == 1 && "Invalid number of operands!");
1125 // Munge the lsb/width into a bitfield mask.
1126 unsigned lsb = Bitfield.LSB;
1127 unsigned width = Bitfield.Width;
1128 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1129 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1130 (32 - (lsb + width)));
1131 Inst.addOperand(MCOperand::CreateImm(Mask));
1132 }
1133
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001134 void addImmOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
1136 addExpr(Inst, getImm());
1137 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001138
Jim Grosbach9d390362011-10-03 23:38:36 +00001139 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1140 assert(N == 1 && "Invalid number of operands!");
1141 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1142 }
1143
Jim Grosbacha77295d2011-09-08 22:07:06 +00001144 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1145 assert(N == 1 && "Invalid number of operands!");
1146 // FIXME: We really want to scale the value here, but the LDRD/STRD
1147 // instruction don't encode operands that way yet.
1148 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1149 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1150 }
1151
Jim Grosbach72f39f82011-08-24 21:22:15 +00001152 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
1154 // The immediate is scaled by four in the encoding and is stored
1155 // in the MCInst as such. Lop off the low two bits here.
1156 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1157 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1158 }
1159
1160 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 // The immediate is scaled by four in the encoding and is stored
1163 // in the MCInst as such. Lop off the low two bits here.
1164 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1165 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1166 }
1167
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001168 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
1170 addExpr(Inst, getImm());
1171 }
1172
Jim Grosbach83ab0702011-07-13 22:01:08 +00001173 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1174 assert(N == 1 && "Invalid number of operands!");
1175 addExpr(Inst, getImm());
1176 }
1177
1178 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1179 assert(N == 1 && "Invalid number of operands!");
1180 addExpr(Inst, getImm());
1181 }
1182
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001183 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1184 assert(N == 1 && "Invalid number of operands!");
1185 addExpr(Inst, getImm());
1186 }
1187
Jim Grosbachf4943352011-07-25 23:09:14 +00001188 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1189 assert(N == 1 && "Invalid number of operands!");
1190 // The constant encodes as the immediate-1, and we store in the instruction
1191 // the bits as encoded, so subtract off one here.
1192 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1193 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1194 }
1195
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001196 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
1198 // The constant encodes as the immediate-1, and we store in the instruction
1199 // the bits as encoded, so subtract off one here.
1200 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1201 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1202 }
1203
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001204 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1205 assert(N == 1 && "Invalid number of operands!");
1206 addExpr(Inst, getImm());
1207 }
1208
Jim Grosbachffa32252011-07-19 19:13:28 +00001209 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1210 assert(N == 1 && "Invalid number of operands!");
1211 addExpr(Inst, getImm());
1212 }
1213
Jim Grosbached838482011-07-26 16:24:27 +00001214 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1215 assert(N == 1 && "Invalid number of operands!");
1216 addExpr(Inst, getImm());
1217 }
1218
Jim Grosbach70939ee2011-08-17 21:51:27 +00001219 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 1 && "Invalid number of operands!");
1221 // The constant encodes as the immediate, except for 32, which encodes as
1222 // zero.
1223 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1224 unsigned Imm = CE->getValue();
1225 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1226 }
1227
Jim Grosbachf6c05252011-07-21 17:23:04 +00001228 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1229 assert(N == 1 && "Invalid number of operands!");
1230 addExpr(Inst, getImm());
1231 }
1232
1233 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1234 assert(N == 1 && "Invalid number of operands!");
1235 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1236 // the instruction as well.
1237 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1238 int Val = CE->getValue();
1239 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1240 }
1241
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001242 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1243 assert(N == 1 && "Invalid number of operands!");
1244 addExpr(Inst, getImm());
1245 }
1246
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001247 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!");
1249 addExpr(Inst, getImm());
1250 }
1251
Jim Grosbach89a63372011-10-28 22:36:30 +00001252 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1253 assert(N == 1 && "Invalid number of operands!");
1254 // The operand is actually a t2_so_imm, but we have its bitwise
1255 // negation in the assembly source, so twiddle it here.
1256 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1257 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1258 }
1259
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001260 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
1262 addExpr(Inst, getImm());
1263 }
1264
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001265 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1266 assert(N == 1 && "Invalid number of operands!");
1267 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1268 }
1269
Jim Grosbach7ce05792011-08-03 23:50:40 +00001270 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1271 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001272 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001273 }
1274
Jim Grosbach57dcb852011-10-11 17:29:55 +00001275 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1276 assert(N == 2 && "Invalid number of operands!");
1277 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1278 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1279 }
1280
Jim Grosbach7ce05792011-08-03 23:50:40 +00001281 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1282 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001283 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1284 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001285 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1286 // Special case for #-0
1287 if (Val == INT32_MIN) Val = 0;
1288 if (Val < 0) Val = -Val;
1289 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1290 } else {
1291 // For register offset, we encode the shift type and negation flag
1292 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001293 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1294 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001295 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001296 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1297 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001298 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001299 }
1300
Jim Grosbach039c2e12011-08-04 23:01:30 +00001301 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1302 assert(N == 2 && "Invalid number of operands!");
1303 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1304 assert(CE && "non-constant AM2OffsetImm operand!");
1305 int32_t Val = CE->getValue();
1306 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1307 // Special case for #-0
1308 if (Val == INT32_MIN) Val = 0;
1309 if (Val < 0) Val = -Val;
1310 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1311 Inst.addOperand(MCOperand::CreateReg(0));
1312 Inst.addOperand(MCOperand::CreateImm(Val));
1313 }
1314
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001315 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1316 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001317 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1318 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001319 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1320 // Special case for #-0
1321 if (Val == INT32_MIN) Val = 0;
1322 if (Val < 0) Val = -Val;
1323 Val = ARM_AM::getAM3Opc(AddSub, Val);
1324 } else {
1325 // For register offset, we encode the shift type and negation flag
1326 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001327 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001328 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001329 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1330 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001331 Inst.addOperand(MCOperand::CreateImm(Val));
1332 }
1333
1334 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1335 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001336 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001337 int32_t Val =
1338 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1339 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1340 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001341 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001342 }
1343
1344 // Constant offset.
1345 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1346 int32_t Val = CE->getValue();
1347 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1348 // Special case for #-0
1349 if (Val == INT32_MIN) Val = 0;
1350 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001351 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001352 Inst.addOperand(MCOperand::CreateReg(0));
1353 Inst.addOperand(MCOperand::CreateImm(Val));
1354 }
1355
Jim Grosbach7ce05792011-08-03 23:50:40 +00001356 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1357 assert(N == 2 && "Invalid number of operands!");
1358 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001359 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001360 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1361 // Special case for #-0
1362 if (Val == INT32_MIN) Val = 0;
1363 if (Val < 0) Val = -Val;
1364 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001365 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001366 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001367 }
1368
Jim Grosbacha77295d2011-09-08 22:07:06 +00001369 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1370 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001371 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1372 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001373 Inst.addOperand(MCOperand::CreateImm(Val));
1374 }
1375
Jim Grosbachb6aed502011-09-09 18:37:27 +00001376 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1377 assert(N == 2 && "Invalid number of operands!");
1378 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001379 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1380 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001381 Inst.addOperand(MCOperand::CreateImm(Val));
1382 }
1383
Jim Grosbach7ce05792011-08-03 23:50:40 +00001384 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1385 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001386 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1387 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001388 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001389 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001390
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001391 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1392 addMemImm8OffsetOperands(Inst, N);
1393 }
1394
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001395 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001396 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001397 }
1398
1399 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1400 assert(N == 2 && "Invalid number of operands!");
1401 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001402 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001403 addExpr(Inst, getImm());
1404 Inst.addOperand(MCOperand::CreateImm(0));
1405 return;
1406 }
1407
1408 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001409 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1410 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001411 Inst.addOperand(MCOperand::CreateImm(Val));
1412 }
1413
Jim Grosbach7ce05792011-08-03 23:50:40 +00001414 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001416 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001417 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001418 addExpr(Inst, getImm());
1419 Inst.addOperand(MCOperand::CreateImm(0));
1420 return;
1421 }
1422
1423 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001424 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1425 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001426 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001427 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001428
Jim Grosbach7f739be2011-09-19 22:21:13 +00001429 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001431 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1432 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001433 }
1434
1435 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1436 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001437 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1438 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001439 }
1440
Jim Grosbach7ce05792011-08-03 23:50:40 +00001441 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001443 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1444 Memory.ShiftImm, Memory.ShiftType);
1445 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1446 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001447 Inst.addOperand(MCOperand::CreateImm(Val));
1448 }
1449
Jim Grosbachab899c12011-09-07 23:10:15 +00001450 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1451 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001452 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1453 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1454 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001455 }
1456
Jim Grosbach7ce05792011-08-03 23:50:40 +00001457 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1458 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001459 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1460 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001461 }
1462
Jim Grosbach60f91a32011-08-19 17:55:24 +00001463 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1464 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001465 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1466 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001467 Inst.addOperand(MCOperand::CreateImm(Val));
1468 }
1469
Jim Grosbach38466302011-08-19 18:55:51 +00001470 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1471 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001472 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1473 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001474 Inst.addOperand(MCOperand::CreateImm(Val));
1475 }
1476
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001477 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1478 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001479 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1480 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001481 Inst.addOperand(MCOperand::CreateImm(Val));
1482 }
1483
Jim Grosbachecd85892011-08-19 18:13:48 +00001484 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1485 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001486 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1487 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001488 Inst.addOperand(MCOperand::CreateImm(Val));
1489 }
1490
Jim Grosbach7ce05792011-08-03 23:50:40 +00001491 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1494 assert(CE && "non-constant post-idx-imm8 operand!");
1495 int Imm = CE->getValue();
1496 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001497 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001498 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1499 Inst.addOperand(MCOperand::CreateImm(Imm));
1500 }
1501
Jim Grosbach2bd01182011-10-11 21:55:36 +00001502 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1503 assert(N == 1 && "Invalid number of operands!");
1504 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1505 assert(CE && "non-constant post-idx-imm8s4 operand!");
1506 int Imm = CE->getValue();
1507 bool isAdd = Imm >= 0;
1508 if (Imm == INT32_MIN) Imm = 0;
1509 // Immediate is scaled by 4.
1510 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1511 Inst.addOperand(MCOperand::CreateImm(Imm));
1512 }
1513
Jim Grosbach7ce05792011-08-03 23:50:40 +00001514 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1515 assert(N == 2 && "Invalid number of operands!");
1516 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001517 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1518 }
1519
1520 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 2 && "Invalid number of operands!");
1522 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1523 // The sign, shift type, and shift amount are encoded in a single operand
1524 // using the AM2 encoding helpers.
1525 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1526 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1527 PostIdxReg.ShiftTy);
1528 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001529 }
1530
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001531 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1534 }
1535
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001536 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1537 assert(N == 1 && "Invalid number of operands!");
1538 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1539 }
1540
Jim Grosbach862019c2011-10-18 23:02:30 +00001541 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1542 assert(N == 1 && "Invalid number of operands!");
1543 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1544 }
1545
Jim Grosbach280dfad2011-10-21 18:54:25 +00001546 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1547 assert(N == 1 && "Invalid number of operands!");
1548 // Only the first register actually goes on the instruction. The rest
1549 // are implied by the opcode.
1550 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1551 }
1552
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001553 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1554 assert(N == 1 && "Invalid number of operands!");
1555 // Only the first register actually goes on the instruction. The rest
1556 // are implied by the opcode.
1557 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1558 }
1559
Jim Grosbachb6310312011-10-21 20:35:01 +00001560 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 // Only the first register actually goes on the instruction. The rest
1563 // are implied by the opcode.
1564 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1565 }
1566
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001567 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1568 assert(N == 1 && "Invalid number of operands!");
1569 // Only the first register actually goes on the instruction. The rest
1570 // are implied by the opcode.
1571 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1572 }
1573
Jim Grosbach460a9052011-10-07 23:56:00 +00001574 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1575 assert(N == 1 && "Invalid number of operands!");
1576 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1577 }
1578
1579 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1580 assert(N == 1 && "Invalid number of operands!");
1581 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1582 }
1583
1584 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1585 assert(N == 1 && "Invalid number of operands!");
1586 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1587 }
1588
Jim Grosbach0e387b22011-10-17 22:26:03 +00001589 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 1 && "Invalid number of operands!");
1591 // The immediate encodes the type of constant as well as the value.
1592 // Mask in that this is an i8 splat.
1593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1594 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1595 }
1596
Jim Grosbachea461102011-10-17 23:09:09 +00001597 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1598 assert(N == 1 && "Invalid number of operands!");
1599 // The immediate encodes the type of constant as well as the value.
1600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1601 unsigned Value = CE->getValue();
1602 if (Value >= 256)
1603 Value = (Value >> 8) | 0xa00;
1604 else
1605 Value |= 0x800;
1606 Inst.addOperand(MCOperand::CreateImm(Value));
1607 }
1608
Jim Grosbach6248a542011-10-18 00:22:00 +00001609 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1610 assert(N == 1 && "Invalid number of operands!");
1611 // The immediate encodes the type of constant as well as the value.
1612 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1613 unsigned Value = CE->getValue();
1614 if (Value >= 256 && Value <= 0xff00)
1615 Value = (Value >> 8) | 0x200;
1616 else if (Value > 0xffff && Value <= 0xff0000)
1617 Value = (Value >> 16) | 0x400;
1618 else if (Value > 0xffffff)
1619 Value = (Value >> 24) | 0x600;
1620 Inst.addOperand(MCOperand::CreateImm(Value));
1621 }
1622
1623 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1624 assert(N == 1 && "Invalid number of operands!");
1625 // The immediate encodes the type of constant as well as the value.
1626 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1627 unsigned Value = CE->getValue();
1628 if (Value >= 256 && Value <= 0xffff)
1629 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1630 else if (Value > 0xffff && Value <= 0xffffff)
1631 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1632 else if (Value > 0xffffff)
1633 Value = (Value >> 24) | 0x600;
1634 Inst.addOperand(MCOperand::CreateImm(Value));
1635 }
1636
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001637 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1638 assert(N == 1 && "Invalid number of operands!");
1639 // The immediate encodes the type of constant as well as the value.
1640 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1641 uint64_t Value = CE->getValue();
1642 unsigned Imm = 0;
1643 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1644 Imm |= (Value & 1) << i;
1645 }
1646 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1647 }
1648
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001649 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001650
Jim Grosbach89df9962011-08-26 21:43:41 +00001651 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001652 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001653 Op->ITMask.Mask = Mask;
1654 Op->StartLoc = S;
1655 Op->EndLoc = S;
1656 return Op;
1657 }
1658
Chris Lattner3a697562010-10-28 17:20:03 +00001659 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001660 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001661 Op->CC.Val = CC;
1662 Op->StartLoc = S;
1663 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001664 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001665 }
1666
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001667 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001668 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001669 Op->Cop.Val = CopVal;
1670 Op->StartLoc = S;
1671 Op->EndLoc = S;
1672 return Op;
1673 }
1674
1675 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001676 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001677 Op->Cop.Val = CopVal;
1678 Op->StartLoc = S;
1679 Op->EndLoc = S;
1680 return Op;
1681 }
1682
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001683 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1684 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1685 Op->Cop.Val = Val;
1686 Op->StartLoc = S;
1687 Op->EndLoc = E;
1688 return Op;
1689 }
1690
Jim Grosbachd67641b2010-12-06 18:21:12 +00001691 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001692 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001693 Op->Reg.RegNum = RegNum;
1694 Op->StartLoc = S;
1695 Op->EndLoc = S;
1696 return Op;
1697 }
1698
Chris Lattner3a697562010-10-28 17:20:03 +00001699 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001700 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001701 Op->Tok.Data = Str.data();
1702 Op->Tok.Length = Str.size();
1703 Op->StartLoc = S;
1704 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001705 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001706 }
1707
Bill Wendling50d0f582010-11-18 23:43:05 +00001708 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001709 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001710 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001711 Op->StartLoc = S;
1712 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001713 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001714 }
1715
Jim Grosbache8606dc2011-07-13 17:50:29 +00001716 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1717 unsigned SrcReg,
1718 unsigned ShiftReg,
1719 unsigned ShiftImm,
1720 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001721 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001722 Op->RegShiftedReg.ShiftTy = ShTy;
1723 Op->RegShiftedReg.SrcReg = SrcReg;
1724 Op->RegShiftedReg.ShiftReg = ShiftReg;
1725 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001726 Op->StartLoc = S;
1727 Op->EndLoc = E;
1728 return Op;
1729 }
1730
Owen Anderson92a20222011-07-21 18:54:16 +00001731 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1732 unsigned SrcReg,
1733 unsigned ShiftImm,
1734 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001735 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001736 Op->RegShiftedImm.ShiftTy = ShTy;
1737 Op->RegShiftedImm.SrcReg = SrcReg;
1738 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001739 Op->StartLoc = S;
1740 Op->EndLoc = E;
1741 return Op;
1742 }
1743
Jim Grosbach580f4a92011-07-25 22:20:28 +00001744 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001745 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001746 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001747 Op->ShifterImm.isASR = isASR;
1748 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001749 Op->StartLoc = S;
1750 Op->EndLoc = E;
1751 return Op;
1752 }
1753
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001754 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001755 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001756 Op->RotImm.Imm = Imm;
1757 Op->StartLoc = S;
1758 Op->EndLoc = E;
1759 return Op;
1760 }
1761
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001762 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1763 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001764 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001765 Op->Bitfield.LSB = LSB;
1766 Op->Bitfield.Width = Width;
1767 Op->StartLoc = S;
1768 Op->EndLoc = E;
1769 return Op;
1770 }
1771
Bill Wendling7729e062010-11-09 22:44:22 +00001772 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001773 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001774 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001775 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001776
Jim Grosbachd300b942011-09-13 22:56:44 +00001777 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001778 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001779 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001780 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001781 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001782
1783 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001784 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001785 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001786 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001787 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001788 Op->StartLoc = StartLoc;
1789 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001790 return Op;
1791 }
1792
Jim Grosbach862019c2011-10-18 23:02:30 +00001793 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1794 SMLoc S, SMLoc E) {
1795 ARMOperand *Op = new ARMOperand(k_VectorList);
1796 Op->VectorList.RegNum = RegNum;
1797 Op->VectorList.Count = Count;
1798 Op->StartLoc = S;
1799 Op->EndLoc = E;
1800 return Op;
1801 }
1802
Jim Grosbach460a9052011-10-07 23:56:00 +00001803 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1804 MCContext &Ctx) {
1805 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1806 Op->VectorIndex.Val = Idx;
1807 Op->StartLoc = S;
1808 Op->EndLoc = E;
1809 return Op;
1810 }
1811
Chris Lattner3a697562010-10-28 17:20:03 +00001812 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001813 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001814 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001815 Op->StartLoc = S;
1816 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001817 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001818 }
1819
Jim Grosbach9d390362011-10-03 23:38:36 +00001820 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001821 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001822 Op->FPImm.Val = Val;
1823 Op->StartLoc = S;
1824 Op->EndLoc = S;
1825 return Op;
1826 }
1827
Jim Grosbach7ce05792011-08-03 23:50:40 +00001828 static ARMOperand *CreateMem(unsigned BaseRegNum,
1829 const MCConstantExpr *OffsetImm,
1830 unsigned OffsetRegNum,
1831 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001832 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001833 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001834 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001835 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001836 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001837 Op->Memory.BaseRegNum = BaseRegNum;
1838 Op->Memory.OffsetImm = OffsetImm;
1839 Op->Memory.OffsetRegNum = OffsetRegNum;
1840 Op->Memory.ShiftType = ShiftType;
1841 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001842 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001843 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001844 Op->StartLoc = S;
1845 Op->EndLoc = E;
1846 return Op;
1847 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001848
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001849 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1850 ARM_AM::ShiftOpc ShiftTy,
1851 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001852 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001853 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001854 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001855 Op->PostIdxReg.isAdd = isAdd;
1856 Op->PostIdxReg.ShiftTy = ShiftTy;
1857 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001858 Op->StartLoc = S;
1859 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001860 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001861 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001862
1863 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001864 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001865 Op->MBOpt.Val = Opt;
1866 Op->StartLoc = S;
1867 Op->EndLoc = S;
1868 return Op;
1869 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001870
1871 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001872 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001873 Op->IFlags.Val = IFlags;
1874 Op->StartLoc = S;
1875 Op->EndLoc = S;
1876 return Op;
1877 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001878
1879 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001880 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001881 Op->MMask.Val = MMask;
1882 Op->StartLoc = S;
1883 Op->EndLoc = S;
1884 return Op;
1885 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001886};
1887
1888} // end anonymous namespace.
1889
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001890void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001891 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001892 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001893 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1894 << ") >";
1895 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001896 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001897 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001898 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001899 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001900 OS << "<ccout " << getReg() << ">";
1901 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001902 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001903 static const char *MaskStr[] = {
1904 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1905 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1906 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001907 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1908 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1909 break;
1910 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001911 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001912 OS << "<coprocessor number: " << getCoproc() << ">";
1913 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001914 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001915 OS << "<coprocessor register: " << getCoproc() << ">";
1916 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001917 case k_CoprocOption:
1918 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1919 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001920 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001921 OS << "<mask: " << getMSRMask() << ">";
1922 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001923 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001924 getImm()->print(OS);
1925 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001926 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001927 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1928 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001929 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001930 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001931 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001932 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001933 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001934 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001935 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1936 << PostIdxReg.RegNum;
1937 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1938 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1939 << PostIdxReg.ShiftImm;
1940 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001941 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001942 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001943 OS << "<ARM_PROC::";
1944 unsigned IFlags = getProcIFlags();
1945 for (int i=2; i >= 0; --i)
1946 if (IFlags & (1 << i))
1947 OS << ARM_PROC::IFlagsToString(1 << i);
1948 OS << ">";
1949 break;
1950 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001951 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001952 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001953 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001954 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001955 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1956 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001957 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001958 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001959 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001960 << RegShiftedReg.SrcReg
1961 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1962 << ", " << RegShiftedReg.ShiftReg << ", "
1963 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001964 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001965 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001966 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001967 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001968 << RegShiftedImm.SrcReg
1969 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1970 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001971 << ">";
1972 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001973 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001974 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1975 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001976 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001977 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1978 << ", width: " << Bitfield.Width << ">";
1979 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001980 case k_RegisterList:
1981 case k_DPRRegisterList:
1982 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001983 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001984
Bill Wendling5fa22a12010-11-09 23:28:44 +00001985 const SmallVectorImpl<unsigned> &RegList = getRegList();
1986 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001987 I = RegList.begin(), E = RegList.end(); I != E; ) {
1988 OS << *I;
1989 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001990 }
1991
1992 OS << ">";
1993 break;
1994 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001995 case k_VectorList:
1996 OS << "<vector_list " << VectorList.Count << " * "
1997 << VectorList.RegNum << ">";
1998 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001999 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002000 OS << "'" << getToken() << "'";
2001 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002002 case k_VectorIndex:
2003 OS << "<vectorindex " << getVectorIndex() << ">";
2004 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002005 }
2006}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002007
2008/// @name Auto-generated Match Functions
2009/// {
2010
2011static unsigned MatchRegisterName(StringRef Name);
2012
2013/// }
2014
Bob Wilson69df7232011-02-03 21:46:10 +00002015bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2016 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002017 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002018
2019 return (RegNo == (unsigned)-1);
2020}
2021
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002022/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002023/// and if it is a register name the token is eaten and the register number is
2024/// returned. Otherwise return -1.
2025///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002026int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002027 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002028 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002029
Chris Lattnere5658fa2010-10-30 04:09:10 +00002030 // FIXME: Validate register for the current architecture; we have to do
2031 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00002032 std::string upperCase = Tok.getString().str();
2033 std::string lowerCase = LowercaseString(upperCase);
2034 unsigned RegNum = MatchRegisterName(lowerCase);
2035 if (!RegNum) {
2036 RegNum = StringSwitch<unsigned>(lowerCase)
2037 .Case("r13", ARM::SP)
2038 .Case("r14", ARM::LR)
2039 .Case("r15", ARM::PC)
2040 .Case("ip", ARM::R12)
2041 .Default(0);
2042 }
2043 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002044
Chris Lattnere5658fa2010-10-30 04:09:10 +00002045 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002046
Chris Lattnere5658fa2010-10-30 04:09:10 +00002047 return RegNum;
2048}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002049
Jim Grosbach19906722011-07-13 18:49:30 +00002050// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2051// If a recoverable error occurs, return 1. If an irrecoverable error
2052// occurs, return -1. An irrecoverable error is one where tokens have been
2053// consumed in the process of trying to parse the shifter (i.e., when it is
2054// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002055int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002056 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2057 SMLoc S = Parser.getTok().getLoc();
2058 const AsmToken &Tok = Parser.getTok();
2059 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2060
2061 std::string upperCase = Tok.getString().str();
2062 std::string lowerCase = LowercaseString(upperCase);
2063 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2064 .Case("lsl", ARM_AM::lsl)
2065 .Case("lsr", ARM_AM::lsr)
2066 .Case("asr", ARM_AM::asr)
2067 .Case("ror", ARM_AM::ror)
2068 .Case("rrx", ARM_AM::rrx)
2069 .Default(ARM_AM::no_shift);
2070
2071 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002072 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002073
Jim Grosbache8606dc2011-07-13 17:50:29 +00002074 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002075
Jim Grosbache8606dc2011-07-13 17:50:29 +00002076 // The source register for the shift has already been added to the
2077 // operand list, so we need to pop it off and combine it into the shifted
2078 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002079 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002080 if (!PrevOp->isReg())
2081 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2082 int SrcReg = PrevOp->getReg();
2083 int64_t Imm = 0;
2084 int ShiftReg = 0;
2085 if (ShiftTy == ARM_AM::rrx) {
2086 // RRX Doesn't have an explicit shift amount. The encoder expects
2087 // the shift register to be the same as the source register. Seems odd,
2088 // but OK.
2089 ShiftReg = SrcReg;
2090 } else {
2091 // Figure out if this is shifted by a constant or a register (for non-RRX).
2092 if (Parser.getTok().is(AsmToken::Hash)) {
2093 Parser.Lex(); // Eat hash.
2094 SMLoc ImmLoc = Parser.getTok().getLoc();
2095 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002096 if (getParser().ParseExpression(ShiftExpr)) {
2097 Error(ImmLoc, "invalid immediate shift value");
2098 return -1;
2099 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002100 // The expression must be evaluatable as an immediate.
2101 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002102 if (!CE) {
2103 Error(ImmLoc, "invalid immediate shift value");
2104 return -1;
2105 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002106 // Range check the immediate.
2107 // lsl, ror: 0 <= imm <= 31
2108 // lsr, asr: 0 <= imm <= 32
2109 Imm = CE->getValue();
2110 if (Imm < 0 ||
2111 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2112 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002113 Error(ImmLoc, "immediate shift value out of range");
2114 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002115 }
2116 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002117 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002118 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002119 if (ShiftReg == -1) {
2120 Error (L, "expected immediate or register in shift operand");
2121 return -1;
2122 }
2123 } else {
2124 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002125 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002126 return -1;
2127 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002128 }
2129
Owen Anderson92a20222011-07-21 18:54:16 +00002130 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2131 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002132 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002133 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002134 else
2135 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2136 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002137
Jim Grosbach19906722011-07-13 18:49:30 +00002138 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002139}
2140
2141
Bill Wendling50d0f582010-11-18 23:43:05 +00002142/// Try to parse a register name. The token must be an Identifier when called.
2143/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2144/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002145///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002146/// TODO this is likely to change to allow different register types and or to
2147/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002148bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002149tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002150 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002151 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002152 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002153 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002154
Bill Wendling50d0f582010-11-18 23:43:05 +00002155 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002156
Chris Lattnere5658fa2010-10-30 04:09:10 +00002157 const AsmToken &ExclaimTok = Parser.getTok();
2158 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002159 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2160 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002161 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002162 return false;
2163 }
2164
2165 // Also check for an index operand. This is only legal for vector registers,
2166 // but that'll get caught OK in operand matching, so we don't need to
2167 // explicitly filter everything else out here.
2168 if (Parser.getTok().is(AsmToken::LBrac)) {
2169 SMLoc SIdx = Parser.getTok().getLoc();
2170 Parser.Lex(); // Eat left bracket token.
2171
2172 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002173 if (getParser().ParseExpression(ImmVal))
2174 return MatchOperand_ParseFail;
2175 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2176 if (!MCE) {
2177 TokError("immediate value expected for vector index");
2178 return MatchOperand_ParseFail;
2179 }
2180
2181 SMLoc E = Parser.getTok().getLoc();
2182 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2183 Error(E, "']' expected");
2184 return MatchOperand_ParseFail;
2185 }
2186
2187 Parser.Lex(); // Eat right bracket token.
2188
2189 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2190 SIdx, E,
2191 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002192 }
2193
Bill Wendling50d0f582010-11-18 23:43:05 +00002194 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002195}
2196
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002197/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2198/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2199/// "c5", ...
2200static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002201 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2202 // but efficient.
2203 switch (Name.size()) {
2204 default: break;
2205 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002206 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002207 return -1;
2208 switch (Name[1]) {
2209 default: return -1;
2210 case '0': return 0;
2211 case '1': return 1;
2212 case '2': return 2;
2213 case '3': return 3;
2214 case '4': return 4;
2215 case '5': return 5;
2216 case '6': return 6;
2217 case '7': return 7;
2218 case '8': return 8;
2219 case '9': return 9;
2220 }
2221 break;
2222 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002223 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002224 return -1;
2225 switch (Name[2]) {
2226 default: return -1;
2227 case '0': return 10;
2228 case '1': return 11;
2229 case '2': return 12;
2230 case '3': return 13;
2231 case '4': return 14;
2232 case '5': return 15;
2233 }
2234 break;
2235 }
2236
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002237 return -1;
2238}
2239
Jim Grosbach89df9962011-08-26 21:43:41 +00002240/// parseITCondCode - Try to parse a condition code for an IT instruction.
2241ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2242parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2243 SMLoc S = Parser.getTok().getLoc();
2244 const AsmToken &Tok = Parser.getTok();
2245 if (!Tok.is(AsmToken::Identifier))
2246 return MatchOperand_NoMatch;
2247 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2248 .Case("eq", ARMCC::EQ)
2249 .Case("ne", ARMCC::NE)
2250 .Case("hs", ARMCC::HS)
2251 .Case("cs", ARMCC::HS)
2252 .Case("lo", ARMCC::LO)
2253 .Case("cc", ARMCC::LO)
2254 .Case("mi", ARMCC::MI)
2255 .Case("pl", ARMCC::PL)
2256 .Case("vs", ARMCC::VS)
2257 .Case("vc", ARMCC::VC)
2258 .Case("hi", ARMCC::HI)
2259 .Case("ls", ARMCC::LS)
2260 .Case("ge", ARMCC::GE)
2261 .Case("lt", ARMCC::LT)
2262 .Case("gt", ARMCC::GT)
2263 .Case("le", ARMCC::LE)
2264 .Case("al", ARMCC::AL)
2265 .Default(~0U);
2266 if (CC == ~0U)
2267 return MatchOperand_NoMatch;
2268 Parser.Lex(); // Eat the token.
2269
2270 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2271
2272 return MatchOperand_Success;
2273}
2274
Jim Grosbach43904292011-07-25 20:14:50 +00002275/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002276/// token must be an Identifier when called, and if it is a coprocessor
2277/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002278ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002279parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002280 SMLoc S = Parser.getTok().getLoc();
2281 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002282 if (Tok.isNot(AsmToken::Identifier))
2283 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002284
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002285 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002286 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002287 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002288
2289 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002290 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002291 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002292}
2293
Jim Grosbach43904292011-07-25 20:14:50 +00002294/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002295/// token must be an Identifier when called, and if it is a coprocessor
2296/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002297ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002298parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002299 SMLoc S = Parser.getTok().getLoc();
2300 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002301 if (Tok.isNot(AsmToken::Identifier))
2302 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002303
2304 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2305 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002306 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002307
2308 Parser.Lex(); // Eat identifier token.
2309 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002310 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002311}
2312
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002313/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2314/// coproc_option : '{' imm0_255 '}'
2315ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2316parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2317 SMLoc S = Parser.getTok().getLoc();
2318
2319 // If this isn't a '{', this isn't a coprocessor immediate operand.
2320 if (Parser.getTok().isNot(AsmToken::LCurly))
2321 return MatchOperand_NoMatch;
2322 Parser.Lex(); // Eat the '{'
2323
2324 const MCExpr *Expr;
2325 SMLoc Loc = Parser.getTok().getLoc();
2326 if (getParser().ParseExpression(Expr)) {
2327 Error(Loc, "illegal expression");
2328 return MatchOperand_ParseFail;
2329 }
2330 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2331 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2332 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2333 return MatchOperand_ParseFail;
2334 }
2335 int Val = CE->getValue();
2336
2337 // Check for and consume the closing '}'
2338 if (Parser.getTok().isNot(AsmToken::RCurly))
2339 return MatchOperand_ParseFail;
2340 SMLoc E = Parser.getTok().getLoc();
2341 Parser.Lex(); // Eat the '}'
2342
2343 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2344 return MatchOperand_Success;
2345}
2346
Jim Grosbachd0588e22011-09-14 18:08:35 +00002347// For register list parsing, we need to map from raw GPR register numbering
2348// to the enumeration values. The enumeration values aren't sorted by
2349// register number due to our using "sp", "lr" and "pc" as canonical names.
2350static unsigned getNextRegister(unsigned Reg) {
2351 // If this is a GPR, we need to do it manually, otherwise we can rely
2352 // on the sort ordering of the enumeration since the other reg-classes
2353 // are sane.
2354 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2355 return Reg + 1;
2356 switch(Reg) {
2357 default: assert(0 && "Invalid GPR number!");
2358 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2359 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2360 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2361 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2362 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2363 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2364 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2365 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2366 }
2367}
2368
2369/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002370bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002371parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002372 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002373 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002374 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002375 Parser.Lex(); // Eat '{' token.
2376 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002377
Jim Grosbachd0588e22011-09-14 18:08:35 +00002378 // Check the first register in the list to see what register class
2379 // this is a list of.
2380 int Reg = tryParseRegister();
2381 if (Reg == -1)
2382 return Error(RegLoc, "register expected");
2383
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002384 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002385 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2386 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2387 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2388 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2389 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2390 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2391 else
2392 return Error(RegLoc, "invalid register in register list");
2393
2394 // The reglist instructions have at most 16 registers, so reserve
2395 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002396 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002397 // Store the first register.
2398 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002399
Jim Grosbachd0588e22011-09-14 18:08:35 +00002400 // This starts immediately after the first register token in the list,
2401 // so we can see either a comma or a minus (range separator) as a legal
2402 // next token.
2403 while (Parser.getTok().is(AsmToken::Comma) ||
2404 Parser.getTok().is(AsmToken::Minus)) {
2405 if (Parser.getTok().is(AsmToken::Minus)) {
2406 Parser.Lex(); // Eat the comma.
2407 SMLoc EndLoc = Parser.getTok().getLoc();
2408 int EndReg = tryParseRegister();
2409 if (EndReg == -1)
2410 return Error(EndLoc, "register expected");
2411 // If the register is the same as the start reg, there's nothing
2412 // more to do.
2413 if (Reg == EndReg)
2414 continue;
2415 // The register must be in the same register class as the first.
2416 if (!RC->contains(EndReg))
2417 return Error(EndLoc, "invalid register in register list");
2418 // Ranges must go from low to high.
2419 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2420 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002421
Jim Grosbachd0588e22011-09-14 18:08:35 +00002422 // Add all the registers in the range to the register list.
2423 while (Reg != EndReg) {
2424 Reg = getNextRegister(Reg);
2425 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2426 }
2427 continue;
2428 }
2429 Parser.Lex(); // Eat the comma.
2430 RegLoc = Parser.getTok().getLoc();
2431 int OldReg = Reg;
2432 Reg = tryParseRegister();
2433 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002434 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002435 // The register must be in the same register class as the first.
2436 if (!RC->contains(Reg))
2437 return Error(RegLoc, "invalid register in register list");
2438 // List must be monotonically increasing.
2439 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2440 return Error(RegLoc, "register list not in ascending order");
2441 // VFP register lists must also be contiguous.
2442 // It's OK to use the enumeration values directly here rather, as the
2443 // VFP register classes have the enum sorted properly.
2444 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2445 Reg != OldReg + 1)
2446 return Error(RegLoc, "non-contiguous register range");
2447 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002448 }
2449
Jim Grosbachd0588e22011-09-14 18:08:35 +00002450 SMLoc E = Parser.getTok().getLoc();
2451 if (Parser.getTok().isNot(AsmToken::RCurly))
2452 return Error(E, "'}' expected");
2453 Parser.Lex(); // Eat '}' token.
2454
Bill Wendling50d0f582010-11-18 23:43:05 +00002455 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2456 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002457}
2458
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002459// Return the low-subreg of a given Q register.
2460static unsigned getDRegFromQReg(unsigned QReg) {
2461 switch (QReg) {
2462 default: llvm_unreachable("expected a Q register!");
2463 case ARM::Q0: return ARM::D0;
2464 case ARM::Q1: return ARM::D2;
2465 case ARM::Q2: return ARM::D4;
2466 case ARM::Q3: return ARM::D6;
2467 case ARM::Q4: return ARM::D8;
2468 case ARM::Q5: return ARM::D10;
2469 case ARM::Q6: return ARM::D12;
2470 case ARM::Q7: return ARM::D14;
2471 case ARM::Q8: return ARM::D16;
2472 case ARM::Q9: return ARM::D19;
2473 case ARM::Q10: return ARM::D20;
2474 case ARM::Q11: return ARM::D22;
2475 case ARM::Q12: return ARM::D24;
2476 case ARM::Q13: return ARM::D26;
2477 case ARM::Q14: return ARM::D28;
2478 case ARM::Q15: return ARM::D30;
2479 }
2480}
2481
Jim Grosbach862019c2011-10-18 23:02:30 +00002482// parse a vector register list
2483ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2484parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2485 if(Parser.getTok().isNot(AsmToken::LCurly))
2486 return MatchOperand_NoMatch;
2487
2488 SMLoc S = Parser.getTok().getLoc();
2489 Parser.Lex(); // Eat '{' token.
2490 SMLoc RegLoc = Parser.getTok().getLoc();
2491
2492 int Reg = tryParseRegister();
2493 if (Reg == -1) {
2494 Error(RegLoc, "register expected");
2495 return MatchOperand_ParseFail;
2496 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002497 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002498 unsigned FirstReg = Reg;
2499 // The list is of D registers, but we also allow Q regs and just interpret
2500 // them as the two D sub-registers.
2501 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2502 FirstReg = Reg = getDRegFromQReg(Reg);
2503 ++Reg;
2504 ++Count;
2505 }
2506
Jim Grosbach862019c2011-10-18 23:02:30 +00002507 while (Parser.getTok().is(AsmToken::Comma)) {
2508 Parser.Lex(); // Eat the comma.
2509 RegLoc = Parser.getTok().getLoc();
2510 int OldReg = Reg;
2511 Reg = tryParseRegister();
2512 if (Reg == -1) {
2513 Error(RegLoc, "register expected");
2514 return MatchOperand_ParseFail;
2515 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002516 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002517 // It's OK to use the enumeration values directly here rather, as the
2518 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002519 //
2520 // The list is of D registers, but we also allow Q regs and just interpret
2521 // them as the two D sub-registers.
2522 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2523 Reg = getDRegFromQReg(Reg);
2524 if (Reg != OldReg + 1) {
2525 Error(RegLoc, "non-contiguous register range");
2526 return MatchOperand_ParseFail;
2527 }
2528 ++Reg;
2529 Count += 2;
2530 continue;
2531 }
2532 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002533 if (Reg != OldReg + 1) {
2534 Error(RegLoc, "non-contiguous register range");
2535 return MatchOperand_ParseFail;
2536 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002537 ++Count;
2538 }
2539
2540 SMLoc E = Parser.getTok().getLoc();
2541 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2542 Error(E, "'}' expected");
2543 return MatchOperand_ParseFail;
2544 }
2545 Parser.Lex(); // Eat '}' token.
2546
2547 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2548 return MatchOperand_Success;
2549}
2550
Jim Grosbach43904292011-07-25 20:14:50 +00002551/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002552ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002553parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002554 SMLoc S = Parser.getTok().getLoc();
2555 const AsmToken &Tok = Parser.getTok();
2556 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2557 StringRef OptStr = Tok.getString();
2558
2559 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2560 .Case("sy", ARM_MB::SY)
2561 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002562 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002563 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002564 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002565 .Case("ishst", ARM_MB::ISHST)
2566 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002567 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002568 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002569 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002570 .Case("osh", ARM_MB::OSH)
2571 .Case("oshst", ARM_MB::OSHST)
2572 .Default(~0U);
2573
2574 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002575 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002576
2577 Parser.Lex(); // Eat identifier token.
2578 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002579 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002580}
2581
Jim Grosbach43904292011-07-25 20:14:50 +00002582/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002583ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002584parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002585 SMLoc S = Parser.getTok().getLoc();
2586 const AsmToken &Tok = Parser.getTok();
2587 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2588 StringRef IFlagsStr = Tok.getString();
2589
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002590 // An iflags string of "none" is interpreted to mean that none of the AIF
2591 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002592 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002593 if (IFlagsStr != "none") {
2594 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2595 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2596 .Case("a", ARM_PROC::A)
2597 .Case("i", ARM_PROC::I)
2598 .Case("f", ARM_PROC::F)
2599 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002600
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002601 // If some specific iflag is already set, it means that some letter is
2602 // present more than once, this is not acceptable.
2603 if (Flag == ~0U || (IFlags & Flag))
2604 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002605
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002606 IFlags |= Flag;
2607 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002608 }
2609
2610 Parser.Lex(); // Eat identifier token.
2611 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2612 return MatchOperand_Success;
2613}
2614
Jim Grosbach43904292011-07-25 20:14:50 +00002615/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002616ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002617parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002618 SMLoc S = Parser.getTok().getLoc();
2619 const AsmToken &Tok = Parser.getTok();
2620 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2621 StringRef Mask = Tok.getString();
2622
James Molloyacad68d2011-09-28 14:21:38 +00002623 if (isMClass()) {
2624 // See ARMv6-M 10.1.1
2625 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2626 .Case("apsr", 0)
2627 .Case("iapsr", 1)
2628 .Case("eapsr", 2)
2629 .Case("xpsr", 3)
2630 .Case("ipsr", 5)
2631 .Case("epsr", 6)
2632 .Case("iepsr", 7)
2633 .Case("msp", 8)
2634 .Case("psp", 9)
2635 .Case("primask", 16)
2636 .Case("basepri", 17)
2637 .Case("basepri_max", 18)
2638 .Case("faultmask", 19)
2639 .Case("control", 20)
2640 .Default(~0U);
2641
2642 if (FlagsVal == ~0U)
2643 return MatchOperand_NoMatch;
2644
2645 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2646 // basepri, basepri_max and faultmask only valid for V7m.
2647 return MatchOperand_NoMatch;
2648
2649 Parser.Lex(); // Eat identifier token.
2650 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2651 return MatchOperand_Success;
2652 }
2653
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002654 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2655 size_t Start = 0, Next = Mask.find('_');
2656 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002657 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002658 if (Next != StringRef::npos)
2659 Flags = Mask.slice(Next+1, Mask.size());
2660
2661 // FlagsVal contains the complete mask:
2662 // 3-0: Mask
2663 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2664 unsigned FlagsVal = 0;
2665
2666 if (SpecReg == "apsr") {
2667 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002668 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002669 .Case("g", 0x4) // same as CPSR_s
2670 .Case("nzcvqg", 0xc) // same as CPSR_fs
2671 .Default(~0U);
2672
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002673 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002674 if (!Flags.empty())
2675 return MatchOperand_NoMatch;
2676 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002677 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002678 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002679 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002680 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2681 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002682 for (int i = 0, e = Flags.size(); i != e; ++i) {
2683 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2684 .Case("c", 1)
2685 .Case("x", 2)
2686 .Case("s", 4)
2687 .Case("f", 8)
2688 .Default(~0U);
2689
2690 // If some specific flag is already set, it means that some letter is
2691 // present more than once, this is not acceptable.
2692 if (FlagsVal == ~0U || (FlagsVal & Flag))
2693 return MatchOperand_NoMatch;
2694 FlagsVal |= Flag;
2695 }
2696 } else // No match for special register.
2697 return MatchOperand_NoMatch;
2698
Owen Anderson7784f1d2011-10-21 18:43:28 +00002699 // Special register without flags is NOT equivalent to "fc" flags.
2700 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2701 // two lines would enable gas compatibility at the expense of breaking
2702 // round-tripping.
2703 //
2704 // if (!FlagsVal)
2705 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002706
2707 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2708 if (SpecReg == "spsr")
2709 FlagsVal |= 16;
2710
2711 Parser.Lex(); // Eat identifier token.
2712 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2713 return MatchOperand_Success;
2714}
2715
Jim Grosbachf6c05252011-07-21 17:23:04 +00002716ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2717parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2718 int Low, int High) {
2719 const AsmToken &Tok = Parser.getTok();
2720 if (Tok.isNot(AsmToken::Identifier)) {
2721 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2722 return MatchOperand_ParseFail;
2723 }
2724 StringRef ShiftName = Tok.getString();
2725 std::string LowerOp = LowercaseString(Op);
2726 std::string UpperOp = UppercaseString(Op);
2727 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2728 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2729 return MatchOperand_ParseFail;
2730 }
2731 Parser.Lex(); // Eat shift type token.
2732
2733 // There must be a '#' and a shift amount.
2734 if (Parser.getTok().isNot(AsmToken::Hash)) {
2735 Error(Parser.getTok().getLoc(), "'#' expected");
2736 return MatchOperand_ParseFail;
2737 }
2738 Parser.Lex(); // Eat hash token.
2739
2740 const MCExpr *ShiftAmount;
2741 SMLoc Loc = Parser.getTok().getLoc();
2742 if (getParser().ParseExpression(ShiftAmount)) {
2743 Error(Loc, "illegal expression");
2744 return MatchOperand_ParseFail;
2745 }
2746 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2747 if (!CE) {
2748 Error(Loc, "constant expression expected");
2749 return MatchOperand_ParseFail;
2750 }
2751 int Val = CE->getValue();
2752 if (Val < Low || Val > High) {
2753 Error(Loc, "immediate value out of range");
2754 return MatchOperand_ParseFail;
2755 }
2756
2757 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2758
2759 return MatchOperand_Success;
2760}
2761
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002762ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2763parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2764 const AsmToken &Tok = Parser.getTok();
2765 SMLoc S = Tok.getLoc();
2766 if (Tok.isNot(AsmToken::Identifier)) {
2767 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2768 return MatchOperand_ParseFail;
2769 }
2770 int Val = StringSwitch<int>(Tok.getString())
2771 .Case("be", 1)
2772 .Case("le", 0)
2773 .Default(-1);
2774 Parser.Lex(); // Eat the token.
2775
2776 if (Val == -1) {
2777 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2778 return MatchOperand_ParseFail;
2779 }
2780 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2781 getContext()),
2782 S, Parser.getTok().getLoc()));
2783 return MatchOperand_Success;
2784}
2785
Jim Grosbach580f4a92011-07-25 22:20:28 +00002786/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2787/// instructions. Legal values are:
2788/// lsl #n 'n' in [0,31]
2789/// asr #n 'n' in [1,32]
2790/// n == 32 encoded as n == 0.
2791ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2792parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2793 const AsmToken &Tok = Parser.getTok();
2794 SMLoc S = Tok.getLoc();
2795 if (Tok.isNot(AsmToken::Identifier)) {
2796 Error(S, "shift operator 'asr' or 'lsl' expected");
2797 return MatchOperand_ParseFail;
2798 }
2799 StringRef ShiftName = Tok.getString();
2800 bool isASR;
2801 if (ShiftName == "lsl" || ShiftName == "LSL")
2802 isASR = false;
2803 else if (ShiftName == "asr" || ShiftName == "ASR")
2804 isASR = true;
2805 else {
2806 Error(S, "shift operator 'asr' or 'lsl' expected");
2807 return MatchOperand_ParseFail;
2808 }
2809 Parser.Lex(); // Eat the operator.
2810
2811 // A '#' and a shift amount.
2812 if (Parser.getTok().isNot(AsmToken::Hash)) {
2813 Error(Parser.getTok().getLoc(), "'#' expected");
2814 return MatchOperand_ParseFail;
2815 }
2816 Parser.Lex(); // Eat hash token.
2817
2818 const MCExpr *ShiftAmount;
2819 SMLoc E = Parser.getTok().getLoc();
2820 if (getParser().ParseExpression(ShiftAmount)) {
2821 Error(E, "malformed shift expression");
2822 return MatchOperand_ParseFail;
2823 }
2824 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2825 if (!CE) {
2826 Error(E, "shift amount must be an immediate");
2827 return MatchOperand_ParseFail;
2828 }
2829
2830 int64_t Val = CE->getValue();
2831 if (isASR) {
2832 // Shift amount must be in [1,32]
2833 if (Val < 1 || Val > 32) {
2834 Error(E, "'asr' shift amount must be in range [1,32]");
2835 return MatchOperand_ParseFail;
2836 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002837 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2838 if (isThumb() && Val == 32) {
2839 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2840 return MatchOperand_ParseFail;
2841 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002842 if (Val == 32) Val = 0;
2843 } else {
2844 // Shift amount must be in [1,32]
2845 if (Val < 0 || Val > 31) {
2846 Error(E, "'lsr' shift amount must be in range [0,31]");
2847 return MatchOperand_ParseFail;
2848 }
2849 }
2850
2851 E = Parser.getTok().getLoc();
2852 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2853
2854 return MatchOperand_Success;
2855}
2856
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002857/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2858/// of instructions. Legal values are:
2859/// ror #n 'n' in {0, 8, 16, 24}
2860ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2861parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2862 const AsmToken &Tok = Parser.getTok();
2863 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002864 if (Tok.isNot(AsmToken::Identifier))
2865 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002866 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002867 if (ShiftName != "ror" && ShiftName != "ROR")
2868 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002869 Parser.Lex(); // Eat the operator.
2870
2871 // A '#' and a rotate amount.
2872 if (Parser.getTok().isNot(AsmToken::Hash)) {
2873 Error(Parser.getTok().getLoc(), "'#' expected");
2874 return MatchOperand_ParseFail;
2875 }
2876 Parser.Lex(); // Eat hash token.
2877
2878 const MCExpr *ShiftAmount;
2879 SMLoc E = Parser.getTok().getLoc();
2880 if (getParser().ParseExpression(ShiftAmount)) {
2881 Error(E, "malformed rotate expression");
2882 return MatchOperand_ParseFail;
2883 }
2884 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2885 if (!CE) {
2886 Error(E, "rotate amount must be an immediate");
2887 return MatchOperand_ParseFail;
2888 }
2889
2890 int64_t Val = CE->getValue();
2891 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2892 // normally, zero is represented in asm by omitting the rotate operand
2893 // entirely.
2894 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2895 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2896 return MatchOperand_ParseFail;
2897 }
2898
2899 E = Parser.getTok().getLoc();
2900 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2901
2902 return MatchOperand_Success;
2903}
2904
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002905ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2906parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2907 SMLoc S = Parser.getTok().getLoc();
2908 // The bitfield descriptor is really two operands, the LSB and the width.
2909 if (Parser.getTok().isNot(AsmToken::Hash)) {
2910 Error(Parser.getTok().getLoc(), "'#' expected");
2911 return MatchOperand_ParseFail;
2912 }
2913 Parser.Lex(); // Eat hash token.
2914
2915 const MCExpr *LSBExpr;
2916 SMLoc E = Parser.getTok().getLoc();
2917 if (getParser().ParseExpression(LSBExpr)) {
2918 Error(E, "malformed immediate expression");
2919 return MatchOperand_ParseFail;
2920 }
2921 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2922 if (!CE) {
2923 Error(E, "'lsb' operand must be an immediate");
2924 return MatchOperand_ParseFail;
2925 }
2926
2927 int64_t LSB = CE->getValue();
2928 // The LSB must be in the range [0,31]
2929 if (LSB < 0 || LSB > 31) {
2930 Error(E, "'lsb' operand must be in the range [0,31]");
2931 return MatchOperand_ParseFail;
2932 }
2933 E = Parser.getTok().getLoc();
2934
2935 // Expect another immediate operand.
2936 if (Parser.getTok().isNot(AsmToken::Comma)) {
2937 Error(Parser.getTok().getLoc(), "too few operands");
2938 return MatchOperand_ParseFail;
2939 }
2940 Parser.Lex(); // Eat hash token.
2941 if (Parser.getTok().isNot(AsmToken::Hash)) {
2942 Error(Parser.getTok().getLoc(), "'#' expected");
2943 return MatchOperand_ParseFail;
2944 }
2945 Parser.Lex(); // Eat hash token.
2946
2947 const MCExpr *WidthExpr;
2948 if (getParser().ParseExpression(WidthExpr)) {
2949 Error(E, "malformed immediate expression");
2950 return MatchOperand_ParseFail;
2951 }
2952 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2953 if (!CE) {
2954 Error(E, "'width' operand must be an immediate");
2955 return MatchOperand_ParseFail;
2956 }
2957
2958 int64_t Width = CE->getValue();
2959 // The LSB must be in the range [1,32-lsb]
2960 if (Width < 1 || Width > 32 - LSB) {
2961 Error(E, "'width' operand must be in the range [1,32-lsb]");
2962 return MatchOperand_ParseFail;
2963 }
2964 E = Parser.getTok().getLoc();
2965
2966 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2967
2968 return MatchOperand_Success;
2969}
2970
Jim Grosbach7ce05792011-08-03 23:50:40 +00002971ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2972parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2973 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002974 // postidx_reg := '+' register {, shift}
2975 // | '-' register {, shift}
2976 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002977
2978 // This method must return MatchOperand_NoMatch without consuming any tokens
2979 // in the case where there is no match, as other alternatives take other
2980 // parse methods.
2981 AsmToken Tok = Parser.getTok();
2982 SMLoc S = Tok.getLoc();
2983 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002984 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002985 int Reg = -1;
2986 if (Tok.is(AsmToken::Plus)) {
2987 Parser.Lex(); // Eat the '+' token.
2988 haveEaten = true;
2989 } else if (Tok.is(AsmToken::Minus)) {
2990 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002991 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002992 haveEaten = true;
2993 }
2994 if (Parser.getTok().is(AsmToken::Identifier))
2995 Reg = tryParseRegister();
2996 if (Reg == -1) {
2997 if (!haveEaten)
2998 return MatchOperand_NoMatch;
2999 Error(Parser.getTok().getLoc(), "register expected");
3000 return MatchOperand_ParseFail;
3001 }
3002 SMLoc E = Parser.getTok().getLoc();
3003
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003004 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3005 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003006 if (Parser.getTok().is(AsmToken::Comma)) {
3007 Parser.Lex(); // Eat the ','.
3008 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3009 return MatchOperand_ParseFail;
3010 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003011
3012 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3013 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003014
3015 return MatchOperand_Success;
3016}
3017
Jim Grosbach251bf252011-08-10 21:56:18 +00003018ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3019parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3020 // Check for a post-index addressing register operand. Specifically:
3021 // am3offset := '+' register
3022 // | '-' register
3023 // | register
3024 // | # imm
3025 // | # + imm
3026 // | # - imm
3027
3028 // This method must return MatchOperand_NoMatch without consuming any tokens
3029 // in the case where there is no match, as other alternatives take other
3030 // parse methods.
3031 AsmToken Tok = Parser.getTok();
3032 SMLoc S = Tok.getLoc();
3033
3034 // Do immediates first, as we always parse those if we have a '#'.
3035 if (Parser.getTok().is(AsmToken::Hash)) {
3036 Parser.Lex(); // Eat the '#'.
3037 // Explicitly look for a '-', as we need to encode negative zero
3038 // differently.
3039 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3040 const MCExpr *Offset;
3041 if (getParser().ParseExpression(Offset))
3042 return MatchOperand_ParseFail;
3043 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3044 if (!CE) {
3045 Error(S, "constant expression expected");
3046 return MatchOperand_ParseFail;
3047 }
3048 SMLoc E = Tok.getLoc();
3049 // Negative zero is encoded as the flag value INT32_MIN.
3050 int32_t Val = CE->getValue();
3051 if (isNegative && Val == 0)
3052 Val = INT32_MIN;
3053
3054 Operands.push_back(
3055 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3056
3057 return MatchOperand_Success;
3058 }
3059
3060
3061 bool haveEaten = false;
3062 bool isAdd = true;
3063 int Reg = -1;
3064 if (Tok.is(AsmToken::Plus)) {
3065 Parser.Lex(); // Eat the '+' token.
3066 haveEaten = true;
3067 } else if (Tok.is(AsmToken::Minus)) {
3068 Parser.Lex(); // Eat the '-' token.
3069 isAdd = false;
3070 haveEaten = true;
3071 }
3072 if (Parser.getTok().is(AsmToken::Identifier))
3073 Reg = tryParseRegister();
3074 if (Reg == -1) {
3075 if (!haveEaten)
3076 return MatchOperand_NoMatch;
3077 Error(Parser.getTok().getLoc(), "register expected");
3078 return MatchOperand_ParseFail;
3079 }
3080 SMLoc E = Parser.getTok().getLoc();
3081
3082 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3083 0, S, E));
3084
3085 return MatchOperand_Success;
3086}
3087
Jim Grosbacha77295d2011-09-08 22:07:06 +00003088/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3089/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3090/// when they refer multiple MIOperands inside a single one.
3091bool ARMAsmParser::
3092cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3093 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3094 // Rt, Rt2
3095 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3096 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3097 // Create a writeback register dummy placeholder.
3098 Inst.addOperand(MCOperand::CreateReg(0));
3099 // addr
3100 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3101 // pred
3102 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3103 return true;
3104}
3105
3106/// cvtT2StrdPre - 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::
3110cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3111 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3112 // Create a writeback register dummy placeholder.
3113 Inst.addOperand(MCOperand::CreateReg(0));
3114 // Rt, Rt2
3115 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3116 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3117 // addr
3118 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3119 // pred
3120 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3121 return true;
3122}
3123
Jim Grosbacheeec0252011-09-08 00:39:19 +00003124/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3125/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3126/// when they refer multiple MIOperands inside a single one.
3127bool ARMAsmParser::
3128cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3129 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3130 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3131
3132 // Create a writeback register dummy placeholder.
3133 Inst.addOperand(MCOperand::CreateImm(0));
3134
3135 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3136 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3137 return true;
3138}
3139
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003140/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3141/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3142/// when they refer multiple MIOperands inside a single one.
3143bool ARMAsmParser::
3144cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3145 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3146 // Create a writeback register dummy placeholder.
3147 Inst.addOperand(MCOperand::CreateImm(0));
3148 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3149 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3150 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3151 return true;
3152}
3153
Jim Grosbach1355cf12011-07-26 17:10:22 +00003154/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003155/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3156/// when they refer multiple MIOperands inside a single one.
3157bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003158cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003159 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3160 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3161
3162 // Create a writeback register dummy placeholder.
3163 Inst.addOperand(MCOperand::CreateImm(0));
3164
Jim Grosbach7ce05792011-08-03 23:50:40 +00003165 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003166 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3167 return true;
3168}
3169
Owen Anderson9ab0f252011-08-26 20:43:14 +00003170/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3171/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3172/// when they refer multiple MIOperands inside a single one.
3173bool ARMAsmParser::
3174cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3175 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3176 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3177
3178 // Create a writeback register dummy placeholder.
3179 Inst.addOperand(MCOperand::CreateImm(0));
3180
3181 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3182 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3183 return true;
3184}
3185
3186
Jim Grosbach548340c2011-08-11 19:22:40 +00003187/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3188/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3189/// when they refer multiple MIOperands inside a single one.
3190bool ARMAsmParser::
3191cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3192 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3193 // Create a writeback register dummy placeholder.
3194 Inst.addOperand(MCOperand::CreateImm(0));
3195 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3196 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3197 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3198 return true;
3199}
3200
Jim Grosbach1355cf12011-07-26 17:10:22 +00003201/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003202/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3203/// when they refer multiple MIOperands inside a single one.
3204bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003205cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003206 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3207 // Create a writeback register dummy placeholder.
3208 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003209 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3210 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3211 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003212 return true;
3213}
3214
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003215/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3216/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3217/// when they refer multiple MIOperands inside a single one.
3218bool ARMAsmParser::
3219cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3220 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3221 // Create a writeback register dummy placeholder.
3222 Inst.addOperand(MCOperand::CreateImm(0));
3223 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3224 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3225 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3226 return true;
3227}
3228
Jim Grosbach7ce05792011-08-03 23:50:40 +00003229/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3230/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3231/// when they refer multiple MIOperands inside a single one.
3232bool ARMAsmParser::
3233cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3234 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3235 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003236 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003237 // Create a writeback register dummy placeholder.
3238 Inst.addOperand(MCOperand::CreateImm(0));
3239 // addr
3240 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3241 // offset
3242 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3243 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003244 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3245 return true;
3246}
3247
Jim Grosbach7ce05792011-08-03 23:50:40 +00003248/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003249/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3250/// when they refer multiple MIOperands inside a single one.
3251bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003252cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3253 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3254 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003255 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003256 // Create a writeback register dummy placeholder.
3257 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003258 // addr
3259 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3260 // offset
3261 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3262 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003263 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3264 return true;
3265}
3266
Jim Grosbach7ce05792011-08-03 23:50:40 +00003267/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003268/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3269/// when they refer multiple MIOperands inside a single one.
3270bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003271cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3272 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003273 // Create a writeback register dummy placeholder.
3274 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003275 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003276 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003277 // addr
3278 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3279 // offset
3280 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3281 // pred
3282 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3283 return true;
3284}
3285
3286/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3287/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3288/// when they refer multiple MIOperands inside a single one.
3289bool ARMAsmParser::
3290cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3291 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3292 // Create a writeback register dummy placeholder.
3293 Inst.addOperand(MCOperand::CreateImm(0));
3294 // Rt
3295 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3296 // addr
3297 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3298 // offset
3299 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3300 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003301 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3302 return true;
3303}
3304
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003305/// cvtLdrdPre - Convert parsed operands to MCInst.
3306/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3307/// when they refer multiple MIOperands inside a single one.
3308bool ARMAsmParser::
3309cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3310 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3311 // Rt, Rt2
3312 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3313 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3314 // Create a writeback register dummy placeholder.
3315 Inst.addOperand(MCOperand::CreateImm(0));
3316 // addr
3317 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3318 // pred
3319 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3320 return true;
3321}
3322
Jim Grosbach14605d12011-08-11 20:28:23 +00003323/// cvtStrdPre - Convert parsed operands to MCInst.
3324/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3325/// when they refer multiple MIOperands inside a single one.
3326bool ARMAsmParser::
3327cvtStrdPre(MCInst &Inst, unsigned Opcode,
3328 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3329 // Create a writeback register dummy placeholder.
3330 Inst.addOperand(MCOperand::CreateImm(0));
3331 // Rt, Rt2
3332 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3333 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3334 // addr
3335 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3336 // pred
3337 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3338 return true;
3339}
3340
Jim Grosbach623a4542011-08-10 22:42:16 +00003341/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3342/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3343/// when they refer multiple MIOperands inside a single one.
3344bool ARMAsmParser::
3345cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3346 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3347 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3348 // Create a writeback register dummy placeholder.
3349 Inst.addOperand(MCOperand::CreateImm(0));
3350 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3351 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3352 return true;
3353}
3354
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003355/// cvtThumbMultiple- Convert parsed operands to MCInst.
3356/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3357/// when they refer multiple MIOperands inside a single one.
3358bool ARMAsmParser::
3359cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3360 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3361 // The second source operand must be the same register as the destination
3362 // operand.
3363 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003364 (((ARMOperand*)Operands[3])->getReg() !=
3365 ((ARMOperand*)Operands[5])->getReg()) &&
3366 (((ARMOperand*)Operands[3])->getReg() !=
3367 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003368 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003369 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003370 return false;
3371 }
3372 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3373 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3374 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003375 // If we have a three-operand form, use that, else the second source operand
3376 // is just the destination operand again.
3377 if (Operands.size() == 6)
3378 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3379 else
3380 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003381 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3382
3383 return true;
3384}
Jim Grosbach623a4542011-08-10 22:42:16 +00003385
Jim Grosbach12431322011-10-24 22:16:58 +00003386bool ARMAsmParser::
3387cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3388 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3389 // Vd
3390 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3391 // Create a writeback register dummy placeholder.
3392 Inst.addOperand(MCOperand::CreateImm(0));
3393 // Vn
3394 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3395 // pred
3396 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3397 return true;
3398}
3399
3400bool ARMAsmParser::
3401cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3402 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3403 // Vd
3404 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3405 // Create a writeback register dummy placeholder.
3406 Inst.addOperand(MCOperand::CreateImm(0));
3407 // Vn
3408 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3409 // Vm
3410 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3411 // pred
3412 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3413 return true;
3414}
3415
Bill Wendlinge7176102010-11-06 22:36:58 +00003416/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003417/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003418bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003419parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003420 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003421 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003422 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003423 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003424 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003425
Sean Callanan18b83232010-01-19 21:44:56 +00003426 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003427 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003428 if (BaseRegNum == -1)
3429 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003430
Daniel Dunbar05710932011-01-18 05:34:17 +00003431 // The next token must either be a comma or a closing bracket.
3432 const AsmToken &Tok = Parser.getTok();
3433 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003434 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003435
Jim Grosbach7ce05792011-08-03 23:50:40 +00003436 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003437 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003438 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003439
Jim Grosbach7ce05792011-08-03 23:50:40 +00003440 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003441 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003442
Jim Grosbachfb12f352011-09-19 18:42:21 +00003443 // If there's a pre-indexing writeback marker, '!', just add it as a token
3444 // operand. It's rather odd, but syntactically valid.
3445 if (Parser.getTok().is(AsmToken::Exclaim)) {
3446 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3447 Parser.Lex(); // Eat the '!'.
3448 }
3449
Jim Grosbach7ce05792011-08-03 23:50:40 +00003450 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003451 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003452
Jim Grosbach7ce05792011-08-03 23:50:40 +00003453 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3454 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003455
Jim Grosbach57dcb852011-10-11 17:29:55 +00003456 // If we have a ':', it's an alignment specifier.
3457 if (Parser.getTok().is(AsmToken::Colon)) {
3458 Parser.Lex(); // Eat the ':'.
3459 E = Parser.getTok().getLoc();
3460
3461 const MCExpr *Expr;
3462 if (getParser().ParseExpression(Expr))
3463 return true;
3464
3465 // The expression has to be a constant. Memory references with relocations
3466 // don't come through here, as they use the <label> forms of the relevant
3467 // instructions.
3468 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3469 if (!CE)
3470 return Error (E, "constant expression expected");
3471
3472 unsigned Align = 0;
3473 switch (CE->getValue()) {
3474 default:
3475 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3476 case 64: Align = 8; break;
3477 case 128: Align = 16; break;
3478 case 256: Align = 32; break;
3479 }
3480
3481 // Now we should have the closing ']'
3482 E = Parser.getTok().getLoc();
3483 if (Parser.getTok().isNot(AsmToken::RBrac))
3484 return Error(E, "']' expected");
3485 Parser.Lex(); // Eat right bracket token.
3486
3487 // Don't worry about range checking the value here. That's handled by
3488 // the is*() predicates.
3489 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3490 ARM_AM::no_shift, 0, Align,
3491 false, S, E));
3492
3493 // If there's a pre-indexing writeback marker, '!', just add it as a token
3494 // operand.
3495 if (Parser.getTok().is(AsmToken::Exclaim)) {
3496 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3497 Parser.Lex(); // Eat the '!'.
3498 }
3499
3500 return false;
3501 }
3502
3503 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003504 // offset.
3505 if (Parser.getTok().is(AsmToken::Hash)) {
3506 Parser.Lex(); // Eat the '#'.
3507 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003508
Owen Anderson0da10cf2011-08-29 19:36:44 +00003509 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003510 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003511 if (getParser().ParseExpression(Offset))
3512 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003513
3514 // The expression has to be a constant. Memory references with relocations
3515 // don't come through here, as they use the <label> forms of the relevant
3516 // instructions.
3517 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3518 if (!CE)
3519 return Error (E, "constant expression expected");
3520
Owen Anderson0da10cf2011-08-29 19:36:44 +00003521 // If the constant was #-0, represent it as INT32_MIN.
3522 int32_t Val = CE->getValue();
3523 if (isNegative && Val == 0)
3524 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3525
Jim Grosbach7ce05792011-08-03 23:50:40 +00003526 // Now we should have the closing ']'
3527 E = Parser.getTok().getLoc();
3528 if (Parser.getTok().isNot(AsmToken::RBrac))
3529 return Error(E, "']' expected");
3530 Parser.Lex(); // Eat right bracket token.
3531
3532 // Don't worry about range checking the value here. That's handled by
3533 // the is*() predicates.
3534 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003535 ARM_AM::no_shift, 0, 0,
3536 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003537
3538 // If there's a pre-indexing writeback marker, '!', just add it as a token
3539 // operand.
3540 if (Parser.getTok().is(AsmToken::Exclaim)) {
3541 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3542 Parser.Lex(); // Eat the '!'.
3543 }
3544
3545 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003546 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003547
3548 // The register offset is optionally preceded by a '+' or '-'
3549 bool isNegative = false;
3550 if (Parser.getTok().is(AsmToken::Minus)) {
3551 isNegative = true;
3552 Parser.Lex(); // Eat the '-'.
3553 } else if (Parser.getTok().is(AsmToken::Plus)) {
3554 // Nothing to do.
3555 Parser.Lex(); // Eat the '+'.
3556 }
3557
3558 E = Parser.getTok().getLoc();
3559 int OffsetRegNum = tryParseRegister();
3560 if (OffsetRegNum == -1)
3561 return Error(E, "register expected");
3562
3563 // If there's a shift operator, handle it.
3564 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003565 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003566 if (Parser.getTok().is(AsmToken::Comma)) {
3567 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003568 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003569 return true;
3570 }
3571
3572 // Now we should have the closing ']'
3573 E = Parser.getTok().getLoc();
3574 if (Parser.getTok().isNot(AsmToken::RBrac))
3575 return Error(E, "']' expected");
3576 Parser.Lex(); // Eat right bracket token.
3577
3578 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003579 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003580 S, E));
3581
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003582 // If there's a pre-indexing writeback marker, '!', just add it as a token
3583 // operand.
3584 if (Parser.getTok().is(AsmToken::Exclaim)) {
3585 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3586 Parser.Lex(); // Eat the '!'.
3587 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003588
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003589 return false;
3590}
3591
Jim Grosbach7ce05792011-08-03 23:50:40 +00003592/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003593/// ( lsl | lsr | asr | ror ) , # shift_amount
3594/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003595/// return true if it parses a shift otherwise it returns false.
3596bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3597 unsigned &Amount) {
3598 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003599 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003600 if (Tok.isNot(AsmToken::Identifier))
3601 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003602 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003603 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003604 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003605 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003606 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003607 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003608 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003609 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003610 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003611 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003612 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003613 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003614 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003615 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003616
Jim Grosbach7ce05792011-08-03 23:50:40 +00003617 // rrx stands alone.
3618 Amount = 0;
3619 if (St != ARM_AM::rrx) {
3620 Loc = Parser.getTok().getLoc();
3621 // A '#' and a shift amount.
3622 const AsmToken &HashTok = Parser.getTok();
3623 if (HashTok.isNot(AsmToken::Hash))
3624 return Error(HashTok.getLoc(), "'#' expected");
3625 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003626
Jim Grosbach7ce05792011-08-03 23:50:40 +00003627 const MCExpr *Expr;
3628 if (getParser().ParseExpression(Expr))
3629 return true;
3630 // Range check the immediate.
3631 // lsl, ror: 0 <= imm <= 31
3632 // lsr, asr: 0 <= imm <= 32
3633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3634 if (!CE)
3635 return Error(Loc, "shift amount must be an immediate");
3636 int64_t Imm = CE->getValue();
3637 if (Imm < 0 ||
3638 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3639 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3640 return Error(Loc, "immediate shift value out of range");
3641 Amount = Imm;
3642 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003643
3644 return false;
3645}
3646
Jim Grosbach9d390362011-10-03 23:38:36 +00003647/// parseFPImm - A floating point immediate expression operand.
3648ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3649parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3650 SMLoc S = Parser.getTok().getLoc();
3651
3652 if (Parser.getTok().isNot(AsmToken::Hash))
3653 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003654
3655 // Disambiguate the VMOV forms that can accept an FP immediate.
3656 // vmov.f32 <sreg>, #imm
3657 // vmov.f64 <dreg>, #imm
3658 // vmov.f32 <dreg>, #imm @ vector f32x2
3659 // vmov.f32 <qreg>, #imm @ vector f32x4
3660 //
3661 // There are also the NEON VMOV instructions which expect an
3662 // integer constant. Make sure we don't try to parse an FPImm
3663 // for these:
3664 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3665 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3666 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3667 TyOp->getToken() != ".f64"))
3668 return MatchOperand_NoMatch;
3669
Jim Grosbach9d390362011-10-03 23:38:36 +00003670 Parser.Lex(); // Eat the '#'.
3671
3672 // Handle negation, as that still comes through as a separate token.
3673 bool isNegative = false;
3674 if (Parser.getTok().is(AsmToken::Minus)) {
3675 isNegative = true;
3676 Parser.Lex();
3677 }
3678 const AsmToken &Tok = Parser.getTok();
3679 if (Tok.is(AsmToken::Real)) {
3680 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3681 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3682 // If we had a '-' in front, toggle the sign bit.
3683 IntVal ^= (uint64_t)isNegative << 63;
3684 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3685 Parser.Lex(); // Eat the token.
3686 if (Val == -1) {
3687 TokError("floating point value out of range");
3688 return MatchOperand_ParseFail;
3689 }
3690 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3691 return MatchOperand_Success;
3692 }
3693 if (Tok.is(AsmToken::Integer)) {
3694 int64_t Val = Tok.getIntVal();
3695 Parser.Lex(); // Eat the token.
3696 if (Val > 255 || Val < 0) {
3697 TokError("encoded floating point value out of range");
3698 return MatchOperand_ParseFail;
3699 }
3700 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3701 return MatchOperand_Success;
3702 }
3703
3704 TokError("invalid floating point immediate");
3705 return MatchOperand_ParseFail;
3706}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003707/// Parse a arm instruction operand. For now this parses the operand regardless
3708/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003709bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003710 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003711 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003712
3713 // Check if the current operand has a custom associated parser, if so, try to
3714 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003715 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3716 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003717 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003718 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3719 // there was a match, but an error occurred, in which case, just return that
3720 // the operand parsing failed.
3721 if (ResTy == MatchOperand_ParseFail)
3722 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003723
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003724 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003725 default:
3726 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003727 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003728 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003729 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003730 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003731 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003732 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003733 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003734 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003735 else if (Res == -1) // irrecoverable error
3736 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003737 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3738 S = Parser.getTok().getLoc();
3739 Parser.Lex();
3740 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3741 return false;
3742 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003743
3744 // Fall though for the Identifier case that is not a register or a
3745 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003746 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003747 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003748 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3749 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003750 // This was not a register so parse other operands that start with an
3751 // identifier (like labels) as expressions and create them as immediates.
3752 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003753 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003754 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003755 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003756 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003757 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3758 return false;
3759 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003760 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003761 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003762 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003763 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003764 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003765 // #42 -> immediate.
3766 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003767 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003768 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003769 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003770 const MCExpr *ImmVal;
3771 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003772 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003773 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3774 if (!CE) {
3775 Error(S, "constant expression expected");
3776 return MatchOperand_ParseFail;
3777 }
3778 int32_t Val = CE->getValue();
3779 if (isNegative && Val == 0)
3780 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003781 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003782 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3783 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003784 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003785 case AsmToken::Colon: {
3786 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003787 // FIXME: Check it's an expression prefix,
3788 // e.g. (FOO - :lower16:BAR) isn't legal.
3789 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003790 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003791 return true;
3792
Evan Cheng75972122011-01-13 07:58:56 +00003793 const MCExpr *SubExprVal;
3794 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003795 return true;
3796
Evan Cheng75972122011-01-13 07:58:56 +00003797 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3798 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003799 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003800 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003801 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003802 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003803 }
3804}
3805
Jim Grosbach1355cf12011-07-26 17:10:22 +00003806// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003807// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003808bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003809 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003810
3811 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003812 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003813 Parser.Lex(); // Eat ':'
3814
3815 if (getLexer().isNot(AsmToken::Identifier)) {
3816 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3817 return true;
3818 }
3819
3820 StringRef IDVal = Parser.getTok().getIdentifier();
3821 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003822 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003823 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003824 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003825 } else {
3826 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3827 return true;
3828 }
3829 Parser.Lex();
3830
3831 if (getLexer().isNot(AsmToken::Colon)) {
3832 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3833 return true;
3834 }
3835 Parser.Lex(); // Eat the last ':'
3836 return false;
3837}
3838
Daniel Dunbar352e1482011-01-11 15:59:50 +00003839/// \brief Given a mnemonic, split out possible predication code and carry
3840/// setting letters to form a canonical mnemonic and flags.
3841//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003842// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003843// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003844StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003845 unsigned &PredicationCode,
3846 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003847 unsigned &ProcessorIMod,
3848 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003849 PredicationCode = ARMCC::AL;
3850 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003851 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003852
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003853 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003854 //
3855 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003856 if ((Mnemonic == "movs" && isThumb()) ||
3857 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3858 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3859 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3860 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3861 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3862 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3863 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003864 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003865
Jim Grosbach3f00e312011-07-11 17:09:57 +00003866 // First, split out any predication code. Ignore mnemonics we know aren't
3867 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003868 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003869 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003870 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003871 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003872 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3873 .Case("eq", ARMCC::EQ)
3874 .Case("ne", ARMCC::NE)
3875 .Case("hs", ARMCC::HS)
3876 .Case("cs", ARMCC::HS)
3877 .Case("lo", ARMCC::LO)
3878 .Case("cc", ARMCC::LO)
3879 .Case("mi", ARMCC::MI)
3880 .Case("pl", ARMCC::PL)
3881 .Case("vs", ARMCC::VS)
3882 .Case("vc", ARMCC::VC)
3883 .Case("hi", ARMCC::HI)
3884 .Case("ls", ARMCC::LS)
3885 .Case("ge", ARMCC::GE)
3886 .Case("lt", ARMCC::LT)
3887 .Case("gt", ARMCC::GT)
3888 .Case("le", ARMCC::LE)
3889 .Case("al", ARMCC::AL)
3890 .Default(~0U);
3891 if (CC != ~0U) {
3892 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3893 PredicationCode = CC;
3894 }
Bill Wendling52925b62010-10-29 23:50:21 +00003895 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003896
Daniel Dunbar352e1482011-01-11 15:59:50 +00003897 // Next, determine if we have a carry setting bit. We explicitly ignore all
3898 // the instructions we know end in 's'.
3899 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003900 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003901 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3902 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3903 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003904 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3905 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003906 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3907 CarrySetting = true;
3908 }
3909
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003910 // The "cps" instruction can have a interrupt mode operand which is glued into
3911 // the mnemonic. Check if this is the case, split it and parse the imod op
3912 if (Mnemonic.startswith("cps")) {
3913 // Split out any imod code.
3914 unsigned IMod =
3915 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3916 .Case("ie", ARM_PROC::IE)
3917 .Case("id", ARM_PROC::ID)
3918 .Default(~0U);
3919 if (IMod != ~0U) {
3920 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3921 ProcessorIMod = IMod;
3922 }
3923 }
3924
Jim Grosbach89df9962011-08-26 21:43:41 +00003925 // The "it" instruction has the condition mask on the end of the mnemonic.
3926 if (Mnemonic.startswith("it")) {
3927 ITMask = Mnemonic.slice(2, Mnemonic.size());
3928 Mnemonic = Mnemonic.slice(0, 2);
3929 }
3930
Daniel Dunbar352e1482011-01-11 15:59:50 +00003931 return Mnemonic;
3932}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003933
3934/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3935/// inclusion of carry set or predication code operands.
3936//
3937// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003938void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003939getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003940 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003941 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3942 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003943 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003944 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003945 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003946 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003947 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003948 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003949 Mnemonic == "mla" || Mnemonic == "smlal" ||
3950 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003951 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003952 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003953 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003954
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003955 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3956 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3957 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3958 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003959 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3960 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003961 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003962 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3963 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3964 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003965 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3966 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003967 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003968 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003969 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003970 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003971
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003972 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003973 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003974 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003975 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003976 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003977}
3978
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003979bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3980 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003981 // FIXME: This is all horribly hacky. We really need a better way to deal
3982 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003983
3984 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3985 // another does not. Specifically, the MOVW instruction does not. So we
3986 // special case it here and remove the defaulted (non-setting) cc_out
3987 // operand if that's the instruction we're trying to match.
3988 //
3989 // We do this as post-processing of the explicit operands rather than just
3990 // conditionally adding the cc_out in the first place because we need
3991 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003992 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003993 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3994 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3995 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3996 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003997
3998 // Register-register 'add' for thumb does not have a cc_out operand
3999 // when there are only two register operands.
4000 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4001 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4002 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4003 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4004 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004005 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004006 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4007 // have to check the immediate range here since Thumb2 has a variant
4008 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004009 if (((isThumb() && Mnemonic == "add") ||
4010 (isThumbTwo() && Mnemonic == "sub")) &&
4011 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004012 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4013 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4014 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004015 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4016 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4017 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004018 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004019 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4020 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004021 // selecting via the generic "add" mnemonic, so to know that we
4022 // should remove the cc_out operand, we have to explicitly check that
4023 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004024 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4025 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004026 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4027 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4028 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4029 // Nest conditions rather than one big 'if' statement for readability.
4030 //
4031 // If either register is a high reg, it's either one of the SP
4032 // variants (handled above) or a 32-bit encoding, so we just
4033 // check against T3.
4034 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4035 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4036 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4037 return false;
4038 // If both registers are low, we're in an IT block, and the immediate is
4039 // in range, we should use encoding T1 instead, which has a cc_out.
4040 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004041 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004042 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4043 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4044 return false;
4045
4046 // Otherwise, we use encoding T4, which does not have a cc_out
4047 // operand.
4048 return true;
4049 }
4050
Jim Grosbach64944f42011-09-14 21:00:40 +00004051 // The thumb2 multiply instruction doesn't have a CCOut register, so
4052 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4053 // use the 16-bit encoding or not.
4054 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4055 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4056 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4057 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4058 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4059 // If the registers aren't low regs, the destination reg isn't the
4060 // same as one of the source regs, or the cc_out operand is zero
4061 // outside of an IT block, we have to use the 32-bit encoding, so
4062 // remove the cc_out operand.
4063 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4064 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4065 !inITBlock() ||
4066 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4067 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4068 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4069 static_cast<ARMOperand*>(Operands[4])->getReg())))
4070 return true;
4071
4072
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004073
Jim Grosbachf69c8042011-08-24 21:42:27 +00004074 // Register-register 'add/sub' for thumb does not have a cc_out operand
4075 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4076 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4077 // right, this will result in better diagnostics (which operand is off)
4078 // anyway.
4079 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4080 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004081 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4082 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4083 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4084 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004085
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004086 return false;
4087}
4088
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004089/// Parse an arm instruction mnemonic followed by its operands.
4090bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4091 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4092 // Create the leading tokens for the mnemonic, split by '.' characters.
4093 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004094 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004095
Daniel Dunbar352e1482011-01-11 15:59:50 +00004096 // Split out the predication code and carry setting flag from the mnemonic.
4097 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004098 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004099 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004100 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004101 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004102 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004103
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004104 // In Thumb1, only the branch (B) instruction can be predicated.
4105 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4106 Parser.EatToEndOfStatement();
4107 return Error(NameLoc, "conditional execution not supported in Thumb1");
4108 }
4109
Jim Grosbachffa32252011-07-19 19:13:28 +00004110 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4111
Jim Grosbach89df9962011-08-26 21:43:41 +00004112 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4113 // is the mask as it will be for the IT encoding if the conditional
4114 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4115 // where the conditional bit0 is zero, the instruction post-processing
4116 // will adjust the mask accordingly.
4117 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004118 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4119 if (ITMask.size() > 3) {
4120 Parser.EatToEndOfStatement();
4121 return Error(Loc, "too many conditions on IT instruction");
4122 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004123 unsigned Mask = 8;
4124 for (unsigned i = ITMask.size(); i != 0; --i) {
4125 char pos = ITMask[i - 1];
4126 if (pos != 't' && pos != 'e') {
4127 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004128 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004129 }
4130 Mask >>= 1;
4131 if (ITMask[i - 1] == 't')
4132 Mask |= 8;
4133 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004134 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004135 }
4136
Jim Grosbachffa32252011-07-19 19:13:28 +00004137 // FIXME: This is all a pretty gross hack. We should automatically handle
4138 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004139
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004140 // Next, add the CCOut and ConditionCode operands, if needed.
4141 //
4142 // For mnemonics which can ever incorporate a carry setting bit or predication
4143 // code, our matching model involves us always generating CCOut and
4144 // ConditionCode operands to match the mnemonic "as written" and then we let
4145 // the matcher deal with finding the right instruction or generating an
4146 // appropriate error.
4147 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004148 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004149
Jim Grosbach33c16a22011-07-14 22:04:21 +00004150 // If we had a carry-set on an instruction that can't do that, issue an
4151 // error.
4152 if (!CanAcceptCarrySet && CarrySetting) {
4153 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004154 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004155 "' can not set flags, but 's' suffix specified");
4156 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004157 // If we had a predication code on an instruction that can't do that, issue an
4158 // error.
4159 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4160 Parser.EatToEndOfStatement();
4161 return Error(NameLoc, "instruction '" + Mnemonic +
4162 "' is not predicable, but condition code specified");
4163 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004164
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004165 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004166 if (CanAcceptCarrySet) {
4167 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004168 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004169 Loc));
4170 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004171
4172 // Add the predication code operand, if necessary.
4173 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004174 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4175 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004176 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004177 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004178 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004179
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004180 // Add the processor imod operand, if necessary.
4181 if (ProcessorIMod) {
4182 Operands.push_back(ARMOperand::CreateImm(
4183 MCConstantExpr::Create(ProcessorIMod, getContext()),
4184 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004185 }
4186
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004187 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004188 while (Next != StringRef::npos) {
4189 Start = Next;
4190 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004191 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004192
Jim Grosbach4d23e992011-08-24 22:19:48 +00004193 // For now, we're only parsing Thumb1 (for the most part), so
4194 // just ignore ".n" qualifiers. We'll use them to restrict
4195 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00004196 if (ExtraToken != ".n") {
4197 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4198 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4199 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004200 }
4201
4202 // Read the remaining operands.
4203 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004204 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004205 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004206 Parser.EatToEndOfStatement();
4207 return true;
4208 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004209
4210 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004211 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004212
4213 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004214 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004215 Parser.EatToEndOfStatement();
4216 return true;
4217 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004218 }
4219 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004220
Chris Lattnercbf8a982010-09-11 16:18:25 +00004221 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004222 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004223 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004224 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004225 }
Bill Wendling146018f2010-11-06 21:42:12 +00004226
Chris Lattner34e53142010-09-08 05:10:46 +00004227 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004228
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004229 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4230 // do and don't have a cc_out optional-def operand. With some spot-checks
4231 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004232 // parse and adjust accordingly before actually matching. We shouldn't ever
4233 // try to remove a cc_out operand that was explicitly set on the the
4234 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4235 // table driven matcher doesn't fit well with the ARM instruction set.
4236 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004237 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4238 Operands.erase(Operands.begin() + 1);
4239 delete Op;
4240 }
4241
Jim Grosbachcf121c32011-07-28 21:57:55 +00004242 // ARM mode 'blx' need special handling, as the register operand version
4243 // is predicable, but the label operand version is not. So, we can't rely
4244 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004245 // a k_CondCode operand in the list. If we're trying to match the label
4246 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004247 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4248 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4249 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4250 Operands.erase(Operands.begin() + 1);
4251 delete Op;
4252 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004253
4254 // The vector-compare-to-zero instructions have a literal token "#0" at
4255 // the end that comes to here as an immediate operand. Convert it to a
4256 // token to play nicely with the matcher.
4257 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4258 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4259 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4260 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4261 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4262 if (CE && CE->getValue() == 0) {
4263 Operands.erase(Operands.begin() + 5);
4264 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4265 delete Op;
4266 }
4267 }
Jim Grosbach68259142011-10-03 22:30:24 +00004268 // VCMP{E} does the same thing, but with a different operand count.
4269 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4270 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4271 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4272 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4273 if (CE && CE->getValue() == 0) {
4274 Operands.erase(Operands.begin() + 4);
4275 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4276 delete Op;
4277 }
4278 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004279 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4280 // end. Convert it to a token here.
4281 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4282 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4283 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4284 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4285 if (CE && CE->getValue() == 0) {
4286 Operands.erase(Operands.begin() + 5);
4287 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4288 delete Op;
4289 }
4290 }
4291
Chris Lattner98986712010-01-14 22:21:20 +00004292 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004293}
4294
Jim Grosbach189610f2011-07-26 18:25:39 +00004295// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004296
4297// return 'true' if register list contains non-low GPR registers,
4298// 'false' otherwise. If Reg is in the register list or is HiReg, set
4299// 'containsReg' to true.
4300static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4301 unsigned HiReg, bool &containsReg) {
4302 containsReg = false;
4303 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4304 unsigned OpReg = Inst.getOperand(i).getReg();
4305 if (OpReg == Reg)
4306 containsReg = true;
4307 // Anything other than a low register isn't legal here.
4308 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4309 return true;
4310 }
4311 return false;
4312}
4313
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004314// Check if the specified regisgter is in the register list of the inst,
4315// starting at the indicated operand number.
4316static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4317 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4318 unsigned OpReg = Inst.getOperand(i).getReg();
4319 if (OpReg == Reg)
4320 return true;
4321 }
4322 return false;
4323}
4324
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004325// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4326// the ARMInsts array) instead. Getting that here requires awkward
4327// API changes, though. Better way?
4328namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004329extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004330}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004331static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004332 return ARMInsts[Opcode];
4333}
4334
Jim Grosbach189610f2011-07-26 18:25:39 +00004335// FIXME: We would really like to be able to tablegen'erate this.
4336bool ARMAsmParser::
4337validateInstruction(MCInst &Inst,
4338 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004339 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004340 SMLoc Loc = Operands[0]->getStartLoc();
4341 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004342 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4343 // being allowed in IT blocks, but not being predicable. It just always
4344 // executes.
4345 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004346 unsigned bit = 1;
4347 if (ITState.FirstCond)
4348 ITState.FirstCond = false;
4349 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004350 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004351 // The instruction must be predicable.
4352 if (!MCID.isPredicable())
4353 return Error(Loc, "instructions in IT block must be predicable");
4354 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4355 unsigned ITCond = bit ? ITState.Cond :
4356 ARMCC::getOppositeCondition(ITState.Cond);
4357 if (Cond != ITCond) {
4358 // Find the condition code Operand to get its SMLoc information.
4359 SMLoc CondLoc;
4360 for (unsigned i = 1; i < Operands.size(); ++i)
4361 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4362 CondLoc = Operands[i]->getStartLoc();
4363 return Error(CondLoc, "incorrect condition in IT block; got '" +
4364 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4365 "', but expected '" +
4366 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4367 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004368 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004369 } else if (isThumbTwo() && MCID.isPredicable() &&
4370 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004371 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4372 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004373 return Error(Loc, "predicated instructions must be in IT block");
4374
Jim Grosbach189610f2011-07-26 18:25:39 +00004375 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004376 case ARM::LDRD:
4377 case ARM::LDRD_PRE:
4378 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004379 case ARM::LDREXD: {
4380 // Rt2 must be Rt + 1.
4381 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4382 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4383 if (Rt2 != Rt + 1)
4384 return Error(Operands[3]->getStartLoc(),
4385 "destination operands must be sequential");
4386 return false;
4387 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004388 case ARM::STRD: {
4389 // Rt2 must be Rt + 1.
4390 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4391 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4392 if (Rt2 != Rt + 1)
4393 return Error(Operands[3]->getStartLoc(),
4394 "source operands must be sequential");
4395 return false;
4396 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004397 case ARM::STRD_PRE:
4398 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004399 case ARM::STREXD: {
4400 // Rt2 must be Rt + 1.
4401 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4402 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4403 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004404 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004405 "source operands must be sequential");
4406 return false;
4407 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004408 case ARM::SBFX:
4409 case ARM::UBFX: {
4410 // width must be in range [1, 32-lsb]
4411 unsigned lsb = Inst.getOperand(2).getImm();
4412 unsigned widthm1 = Inst.getOperand(3).getImm();
4413 if (widthm1 >= 32 - lsb)
4414 return Error(Operands[5]->getStartLoc(),
4415 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004416 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004417 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004418 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004419 // If we're parsing Thumb2, the .w variant is available and handles
4420 // most cases that are normally illegal for a Thumb1 LDM
4421 // instruction. We'll make the transformation in processInstruction()
4422 // if necessary.
4423 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004424 // Thumb LDM instructions are writeback iff the base register is not
4425 // in the register list.
4426 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004427 bool hasWritebackToken =
4428 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4429 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004430 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004431 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004432 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4433 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004434 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004435 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004436 return Error(Operands[2]->getStartLoc(),
4437 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004438 // If we should not have writeback, there must not be a '!'. This is
4439 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004440 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004441 return Error(Operands[3]->getStartLoc(),
4442 "writeback operator '!' not allowed when base register "
4443 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004444
4445 break;
4446 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004447 case ARM::t2LDMIA_UPD: {
4448 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4449 return Error(Operands[4]->getStartLoc(),
4450 "writeback operator '!' not allowed when base register "
4451 "in register list");
4452 break;
4453 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004454 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004455 bool listContainsBase;
4456 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4457 return Error(Operands[2]->getStartLoc(),
4458 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004459 break;
4460 }
4461 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004462 bool listContainsBase;
4463 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4464 return Error(Operands[2]->getStartLoc(),
4465 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004466 break;
4467 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004468 case ARM::tSTMIA_UPD: {
4469 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004470 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004471 return Error(Operands[4]->getStartLoc(),
4472 "registers must be in range r0-r7");
4473 break;
4474 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004475 }
4476
4477 return false;
4478}
4479
Jim Grosbachf8fce712011-08-11 17:35:48 +00004480void ARMAsmParser::
4481processInstruction(MCInst &Inst,
4482 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4483 switch (Inst.getOpcode()) {
4484 case ARM::LDMIA_UPD:
4485 // If this is a load of a single register via a 'pop', then we should use
4486 // a post-indexed LDR instruction instead, per the ARM ARM.
4487 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4488 Inst.getNumOperands() == 5) {
4489 MCInst TmpInst;
4490 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4491 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4492 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4493 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4494 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4495 TmpInst.addOperand(MCOperand::CreateImm(4));
4496 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4497 TmpInst.addOperand(Inst.getOperand(3));
4498 Inst = TmpInst;
4499 }
4500 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004501 case ARM::STMDB_UPD:
4502 // If this is a store of a single register via a 'push', then we should use
4503 // a pre-indexed STR instruction instead, per the ARM ARM.
4504 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4505 Inst.getNumOperands() == 5) {
4506 MCInst TmpInst;
4507 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4508 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4509 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4510 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4511 TmpInst.addOperand(MCOperand::CreateImm(-4));
4512 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4513 TmpInst.addOperand(Inst.getOperand(3));
4514 Inst = TmpInst;
4515 }
4516 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004517 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004518 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4519 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4520 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4521 // to encoding T1 if <Rd> is omitted."
4522 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004523 Inst.setOpcode(ARM::tADDi3);
4524 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004525 case ARM::tSUBi8:
4526 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4527 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4528 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4529 // to encoding T1 if <Rd> is omitted."
4530 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4531 Inst.setOpcode(ARM::tSUBi3);
4532 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004533 case ARM::tB:
4534 // A Thumb conditional branch outside of an IT block is a tBcc.
4535 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4536 Inst.setOpcode(ARM::tBcc);
4537 break;
4538 case ARM::t2B:
4539 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4540 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4541 Inst.setOpcode(ARM::t2Bcc);
4542 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004543 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004544 // If the conditional is AL or we're in an IT block, we really want t2B.
4545 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004546 Inst.setOpcode(ARM::t2B);
4547 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004548 case ARM::tBcc:
4549 // If the conditional is AL, we really want tB.
4550 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4551 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004552 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004553 case ARM::tLDMIA: {
4554 // If the register list contains any high registers, or if the writeback
4555 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4556 // instead if we're in Thumb2. Otherwise, this should have generated
4557 // an error in validateInstruction().
4558 unsigned Rn = Inst.getOperand(0).getReg();
4559 bool hasWritebackToken =
4560 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4561 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4562 bool listContainsBase;
4563 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4564 (!listContainsBase && !hasWritebackToken) ||
4565 (listContainsBase && hasWritebackToken)) {
4566 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4567 assert (isThumbTwo());
4568 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4569 // If we're switching to the updating version, we need to insert
4570 // the writeback tied operand.
4571 if (hasWritebackToken)
4572 Inst.insert(Inst.begin(),
4573 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4574 }
4575 break;
4576 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004577 case ARM::tSTMIA_UPD: {
4578 // If the register list contains any high registers, we need to use
4579 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4580 // should have generated an error in validateInstruction().
4581 unsigned Rn = Inst.getOperand(0).getReg();
4582 bool listContainsBase;
4583 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4584 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4585 assert (isThumbTwo());
4586 Inst.setOpcode(ARM::t2STMIA_UPD);
4587 }
4588 break;
4589 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004590 case ARM::t2MOVi: {
4591 // If we can use the 16-bit encoding and the user didn't explicitly
4592 // request the 32-bit variant, transform it here.
4593 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4594 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004595 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4596 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4597 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004598 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4599 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4600 // The operands aren't in the same order for tMOVi8...
4601 MCInst TmpInst;
4602 TmpInst.setOpcode(ARM::tMOVi8);
4603 TmpInst.addOperand(Inst.getOperand(0));
4604 TmpInst.addOperand(Inst.getOperand(4));
4605 TmpInst.addOperand(Inst.getOperand(1));
4606 TmpInst.addOperand(Inst.getOperand(2));
4607 TmpInst.addOperand(Inst.getOperand(3));
4608 Inst = TmpInst;
4609 }
4610 break;
4611 }
4612 case ARM::t2MOVr: {
4613 // If we can use the 16-bit encoding and the user didn't explicitly
4614 // request the 32-bit variant, transform it here.
4615 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4616 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4617 Inst.getOperand(2).getImm() == ARMCC::AL &&
4618 Inst.getOperand(4).getReg() == ARM::CPSR &&
4619 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4620 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4621 // The operands aren't the same for tMOV[S]r... (no cc_out)
4622 MCInst TmpInst;
4623 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4624 TmpInst.addOperand(Inst.getOperand(0));
4625 TmpInst.addOperand(Inst.getOperand(1));
4626 TmpInst.addOperand(Inst.getOperand(2));
4627 TmpInst.addOperand(Inst.getOperand(3));
4628 Inst = TmpInst;
4629 }
4630 break;
4631 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004632 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004633 case ARM::t2SXTB:
4634 case ARM::t2UXTH:
4635 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004636 // If we can use the 16-bit encoding and the user didn't explicitly
4637 // request the 32-bit variant, transform it here.
4638 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4639 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4640 Inst.getOperand(2).getImm() == 0 &&
4641 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4642 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004643 unsigned NewOpc;
4644 switch (Inst.getOpcode()) {
4645 default: llvm_unreachable("Illegal opcode!");
4646 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4647 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4648 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4649 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4650 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004651 // The operands aren't the same for thumb1 (no rotate operand).
4652 MCInst TmpInst;
4653 TmpInst.setOpcode(NewOpc);
4654 TmpInst.addOperand(Inst.getOperand(0));
4655 TmpInst.addOperand(Inst.getOperand(1));
4656 TmpInst.addOperand(Inst.getOperand(3));
4657 TmpInst.addOperand(Inst.getOperand(4));
4658 Inst = TmpInst;
4659 }
4660 break;
4661 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004662 case ARM::t2IT: {
4663 // The mask bits for all but the first condition are represented as
4664 // the low bit of the condition code value implies 't'. We currently
4665 // always have 1 implies 't', so XOR toggle the bits if the low bit
4666 // of the condition code is zero. The encoding also expects the low
4667 // bit of the condition to be encoded as bit 4 of the mask operand,
4668 // so mask that in if needed
4669 MCOperand &MO = Inst.getOperand(1);
4670 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004671 unsigned OrigMask = Mask;
4672 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004673 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004674 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4675 for (unsigned i = 3; i != TZ; --i)
4676 Mask ^= 1 << i;
4677 } else
4678 Mask |= 0x10;
4679 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004680
4681 // Set up the IT block state according to the IT instruction we just
4682 // matched.
4683 assert(!inITBlock() && "nested IT blocks?!");
4684 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4685 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4686 ITState.CurPosition = 0;
4687 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004688 break;
4689 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004690 }
4691}
4692
Jim Grosbach47a0d522011-08-16 20:45:50 +00004693unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4694 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4695 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004696 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004697 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004698 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4699 assert(MCID.hasOptionalDef() &&
4700 "optionally flag setting instruction missing optional def operand");
4701 assert(MCID.NumOperands == Inst.getNumOperands() &&
4702 "operand count mismatch!");
4703 // Find the optional-def operand (cc_out).
4704 unsigned OpNo;
4705 for (OpNo = 0;
4706 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4707 ++OpNo)
4708 ;
4709 // If we're parsing Thumb1, reject it completely.
4710 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4711 return Match_MnemonicFail;
4712 // If we're parsing Thumb2, which form is legal depends on whether we're
4713 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004714 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4715 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004716 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004717 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4718 inITBlock())
4719 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004720 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004721 // Some high-register supporting Thumb1 encodings only allow both registers
4722 // to be from r0-r7 when in Thumb2.
4723 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4724 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4725 isARMLowRegister(Inst.getOperand(2).getReg()))
4726 return Match_RequiresThumb2;
4727 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004728 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004729 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4730 isARMLowRegister(Inst.getOperand(1).getReg()))
4731 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004732 return Match_Success;
4733}
4734
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004735bool ARMAsmParser::
4736MatchAndEmitInstruction(SMLoc IDLoc,
4737 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4738 MCStreamer &Out) {
4739 MCInst Inst;
4740 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004741 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004742 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004743 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004744 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004745 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004746 // Context sensitive operand constraints aren't handled by the matcher,
4747 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004748 if (validateInstruction(Inst, Operands)) {
4749 // Still progress the IT block, otherwise one wrong condition causes
4750 // nasty cascading errors.
4751 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004752 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004753 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004754
Jim Grosbachf8fce712011-08-11 17:35:48 +00004755 // Some instructions need post-processing to, for example, tweak which
4756 // encoding is selected.
4757 processInstruction(Inst, Operands);
4758
Jim Grosbacha1109882011-09-02 23:22:08 +00004759 // Only move forward at the very end so that everything in validate
4760 // and process gets a consistent answer about whether we're in an IT
4761 // block.
4762 forwardITPosition();
4763
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004764 Out.EmitInstruction(Inst);
4765 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004766 case Match_MissingFeature:
4767 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4768 return true;
4769 case Match_InvalidOperand: {
4770 SMLoc ErrorLoc = IDLoc;
4771 if (ErrorInfo != ~0U) {
4772 if (ErrorInfo >= Operands.size())
4773 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004774
Chris Lattnere73d4f82010-10-28 21:41:58 +00004775 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4776 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4777 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004778
Chris Lattnere73d4f82010-10-28 21:41:58 +00004779 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004780 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004781 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004782 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004783 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004784 // The converter function will have already emited a diagnostic.
4785 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004786 case Match_RequiresNotITBlock:
4787 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004788 case Match_RequiresITBlock:
4789 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004790 case Match_RequiresV6:
4791 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4792 case Match_RequiresThumb2:
4793 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004794 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004795
Eric Christopherc223e2b2010-10-29 09:26:59 +00004796 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004797 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004798}
4799
Jim Grosbach1355cf12011-07-26 17:10:22 +00004800/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004801bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4802 StringRef IDVal = DirectiveID.getIdentifier();
4803 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004804 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004805 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004806 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004807 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004808 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004809 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004810 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004811 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004812 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004813 return true;
4814}
4815
Jim Grosbach1355cf12011-07-26 17:10:22 +00004816/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004817/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004818bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004819 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4820 for (;;) {
4821 const MCExpr *Value;
4822 if (getParser().ParseExpression(Value))
4823 return true;
4824
Chris Lattneraaec2052010-01-19 19:46:13 +00004825 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004826
4827 if (getLexer().is(AsmToken::EndOfStatement))
4828 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004829
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004830 // FIXME: Improve diagnostic.
4831 if (getLexer().isNot(AsmToken::Comma))
4832 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004833 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004834 }
4835 }
4836
Sean Callananb9a25b72010-01-19 20:27:46 +00004837 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004838 return false;
4839}
4840
Jim Grosbach1355cf12011-07-26 17:10:22 +00004841/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004842/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004843bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004844 if (getLexer().isNot(AsmToken::EndOfStatement))
4845 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004846 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004847
4848 // TODO: set thumb mode
4849 // TODO: tell the MC streamer the mode
4850 // getParser().getStreamer().Emit???();
4851 return false;
4852}
4853
Jim Grosbach1355cf12011-07-26 17:10:22 +00004854/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004855/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004856bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004857 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4858 bool isMachO = MAI.hasSubsectionsViaSymbols();
4859 StringRef Name;
4860
4861 // Darwin asm has function name after .thumb_func direction
4862 // ELF doesn't
4863 if (isMachO) {
4864 const AsmToken &Tok = Parser.getTok();
4865 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4866 return Error(L, "unexpected token in .thumb_func directive");
4867 Name = Tok.getString();
4868 Parser.Lex(); // Consume the identifier token.
4869 }
4870
Kevin Enderby515d5092009-10-15 20:48:48 +00004871 if (getLexer().isNot(AsmToken::EndOfStatement))
4872 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004873 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004874
Rafael Espindola64695402011-05-16 16:17:21 +00004875 // FIXME: assuming function name will be the line following .thumb_func
4876 if (!isMachO) {
4877 Name = Parser.getTok().getString();
4878 }
4879
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004880 // Mark symbol as a thumb symbol.
4881 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4882 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004883 return false;
4884}
4885
Jim Grosbach1355cf12011-07-26 17:10:22 +00004886/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004887/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004888bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004889 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004890 if (Tok.isNot(AsmToken::Identifier))
4891 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004892 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004893 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004894 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004895 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004896 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004897 else
4898 return Error(L, "unrecognized syntax mode in .syntax directive");
4899
4900 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004901 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004902 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004903
4904 // TODO tell the MC streamer the mode
4905 // getParser().getStreamer().Emit???();
4906 return false;
4907}
4908
Jim Grosbach1355cf12011-07-26 17:10:22 +00004909/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004910/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004911bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004912 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004913 if (Tok.isNot(AsmToken::Integer))
4914 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004915 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004916 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004917 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004918 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004919 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004920 else
4921 return Error(L, "invalid operand to .code directive");
4922
4923 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004924 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004925 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004926
Evan Cheng32869202011-07-08 22:36:29 +00004927 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004928 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004929 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004930 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004931 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004932 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004933 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004934 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004935 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004936
Kevin Enderby515d5092009-10-15 20:48:48 +00004937 return false;
4938}
4939
Sean Callanan90b70972010-04-07 20:29:34 +00004940extern "C" void LLVMInitializeARMAsmLexer();
4941
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004942/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004943extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004944 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4945 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004946 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004947}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004948
Chris Lattner0692ee62010-09-06 19:11:01 +00004949#define GET_REGISTER_MATCHER
4950#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004951#include "ARMGenAsmMatcher.inc"