blob: a13554f88266af90e857e2881109b9f456863e93 [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 Grosbach189610f2011-07-26 18:25:39 +0000201
202 bool validateInstruction(MCInst &Inst,
203 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000204 void processInstruction(MCInst &Inst,
205 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000206 bool shouldOmitCCOutOperand(StringRef Mnemonic,
207 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000208
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000209public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000210 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000211 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000212 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000213 Match_RequiresV6,
214 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000215 };
216
Evan Chengffc0e732011-07-09 05:47:46 +0000217 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000218 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000219 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000220
Evan Chengebdeeab2011-07-08 01:53:10 +0000221 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000222 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000223
224 // Not in an ITBlock to start with.
225 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000226 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227
Jim Grosbach1355cf12011-07-26 17:10:22 +0000228 // Implementation of the MCTargetAsmParser interface:
229 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
230 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000231 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000232 bool ParseDirective(AsmToken DirectiveID);
233
Jim Grosbach47a0d522011-08-16 20:45:50 +0000234 unsigned checkTargetMatchPredicate(MCInst &Inst);
235
Jim Grosbach1355cf12011-07-26 17:10:22 +0000236 bool MatchAndEmitInstruction(SMLoc IDLoc,
237 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
238 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000239};
Jim Grosbach16c74252010-10-29 14:46:02 +0000240} // end anonymous namespace
241
Chris Lattner3a697562010-10-28 17:20:03 +0000242namespace {
243
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000244/// ARMOperand - Instances of this class represent a parsed ARM machine
245/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000246class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000247 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000248 k_CondCode,
249 k_CCOut,
250 k_ITCondMask,
251 k_CoprocNum,
252 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000253 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000254 k_Immediate,
255 k_FPImmediate,
256 k_MemBarrierOpt,
257 k_Memory,
258 k_PostIndexRegister,
259 k_MSRMask,
260 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000261 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000262 k_Register,
263 k_RegisterList,
264 k_DPRRegisterList,
265 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000266 k_VectorList,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000267 k_ShiftedRegister,
268 k_ShiftedImmediate,
269 k_ShifterImmediate,
270 k_RotateImmediate,
271 k_BitfieldDescriptor,
272 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000273 } Kind;
274
Sean Callanan76264762010-04-02 22:27:05 +0000275 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000276 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000277
278 union {
279 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000280 ARMCC::CondCodes Val;
281 } CC;
282
283 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000284 unsigned Val;
285 } Cop;
286
287 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000288 unsigned Val;
289 } CoprocOption;
290
291 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000292 unsigned Mask:4;
293 } ITMask;
294
295 struct {
296 ARM_MB::MemBOpt Val;
297 } MBOpt;
298
299 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000300 ARM_PROC::IFlags Val;
301 } IFlags;
302
303 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000304 unsigned Val;
305 } MMask;
306
307 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000308 const char *Data;
309 unsigned Length;
310 } Tok;
311
312 struct {
313 unsigned RegNum;
314 } Reg;
315
Jim Grosbach862019c2011-10-18 23:02:30 +0000316 // A vector register list is a sequential list of 1 to 4 registers.
317 struct {
318 unsigned RegNum;
319 unsigned Count;
320 } VectorList;
321
Bill Wendling8155e5b2010-11-06 22:19:43 +0000322 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000323 unsigned Val;
324 } VectorIndex;
325
326 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000327 const MCExpr *Val;
328 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000329
Jim Grosbach9d390362011-10-03 23:38:36 +0000330 struct {
331 unsigned Val; // encoded 8-bit representation
332 } FPImm;
333
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000334 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000335 struct {
336 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000337 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
338 // was specified.
339 const MCConstantExpr *OffsetImm; // Offset immediate value
340 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
341 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000342 unsigned ShiftImm; // shift for OffsetReg.
343 unsigned Alignment; // 0 = no alignment specified
344 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000345 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000346 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000347
348 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000349 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000350 bool isAdd;
351 ARM_AM::ShiftOpc ShiftTy;
352 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000353 } PostIdxReg;
354
355 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000356 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000357 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000358 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000359 struct {
360 ARM_AM::ShiftOpc ShiftTy;
361 unsigned SrcReg;
362 unsigned ShiftReg;
363 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000364 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000365 struct {
366 ARM_AM::ShiftOpc ShiftTy;
367 unsigned SrcReg;
368 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000369 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000370 struct {
371 unsigned Imm;
372 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000373 struct {
374 unsigned LSB;
375 unsigned Width;
376 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000377 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000378
Bill Wendling146018f2010-11-06 21:42:12 +0000379 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
380public:
Sean Callanan76264762010-04-02 22:27:05 +0000381 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
382 Kind = o.Kind;
383 StartLoc = o.StartLoc;
384 EndLoc = o.EndLoc;
385 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000386 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000387 CC = o.CC;
388 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000389 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000390 ITMask = o.ITMask;
391 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000392 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000393 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000394 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000395 case k_CCOut:
396 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000397 Reg = o.Reg;
398 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_RegisterList:
400 case k_DPRRegisterList:
401 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000402 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000403 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000404 case k_VectorList:
405 VectorList = o.VectorList;
406 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000407 case k_CoprocNum:
408 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000409 Cop = o.Cop;
410 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000411 case k_CoprocOption:
412 CoprocOption = o.CoprocOption;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000415 Imm = o.Imm;
416 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000417 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000418 FPImm = o.FPImm;
419 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000420 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000421 MBOpt = o.MBOpt;
422 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000423 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000424 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000427 PostIdxReg = o.PostIdxReg;
428 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000429 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000430 MMask = o.MMask;
431 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000432 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000433 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000434 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000435 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000436 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000439 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000442 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000445 RotImm = o.RotImm;
446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000448 Bitfield = o.Bitfield;
449 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000450 case k_VectorIndex:
451 VectorIndex = o.VectorIndex;
452 break;
Sean Callanan76264762010-04-02 22:27:05 +0000453 }
454 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000455
Sean Callanan76264762010-04-02 22:27:05 +0000456 /// getStartLoc - Get the location of the first token of this operand.
457 SMLoc getStartLoc() const { return StartLoc; }
458 /// getEndLoc - Get the location of the last token of this operand.
459 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000460
Daniel Dunbar8462b302010-08-11 06:36:53 +0000461 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000463 return CC.Val;
464 }
465
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000466 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000467 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000468 return Cop.Val;
469 }
470
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000471 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000472 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000473 return StringRef(Tok.Data, Tok.Length);
474 }
475
476 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000477 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000478 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000479 }
480
Bill Wendling5fa22a12010-11-09 23:28:44 +0000481 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
483 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000484 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000485 }
486
Kevin Enderbycfe07242009-10-13 22:19:02 +0000487 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000488 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000489 return Imm.Val;
490 }
491
Jim Grosbach9d390362011-10-03 23:38:36 +0000492 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000494 return FPImm.Val;
495 }
496
Jim Grosbach460a9052011-10-07 23:56:00 +0000497 unsigned getVectorIndex() const {
498 assert(Kind == k_VectorIndex && "Invalid access!");
499 return VectorIndex.Val;
500 }
501
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000502 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000503 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000504 return MBOpt.Val;
505 }
506
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000507 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000508 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000509 return IFlags.Val;
510 }
511
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000512 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000513 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000514 return MMask.Val;
515 }
516
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000517 bool isCoprocNum() const { return Kind == k_CoprocNum; }
518 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000519 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000520 bool isCondCode() const { return Kind == k_CondCode; }
521 bool isCCOut() const { return Kind == k_CCOut; }
522 bool isITMask() const { return Kind == k_ITCondMask; }
523 bool isITCondCode() const { return Kind == k_CondCode; }
524 bool isImm() const { return Kind == k_Immediate; }
525 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000526 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000528 return false;
529 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
530 if (!CE) return false;
531 int64_t Value = CE->getValue();
532 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
533 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000534 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000535 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000536 return false;
537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
538 if (!CE) return false;
539 int64_t Value = CE->getValue();
540 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
541 }
542 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000543 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000544 return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
549 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000550 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return Value >= 0 && Value < 256;
557 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000558 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return Value >= 0 && Value < 8;
565 }
566 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return Value >= 0 && Value < 16;
573 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000574 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000575 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 32;
581 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000582 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000583 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value > 0 && Value < 17;
589 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000590 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000591 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value > 0 && Value < 33;
597 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000598 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000600 return false;
601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 65536;
605 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000606 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 // If it's not a constant expression, it'll generate a fixup and be
611 // handled later.
612 if (!CE) return true;
613 int64_t Value = CE->getValue();
614 return Value >= 0 && Value < 65536;
615 }
Jim Grosbached838482011-07-26 16:24:27 +0000616 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000617 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000618 return false;
619 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
620 if (!CE) return false;
621 int64_t Value = CE->getValue();
622 return Value >= 0 && Value <= 0xffffff;
623 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000624 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000625 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000626 return false;
627 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
628 if (!CE) return false;
629 int64_t Value = CE->getValue();
630 return Value > 0 && Value < 33;
631 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000632 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000633 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000634 return false;
635 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
636 if (!CE) return false;
637 int64_t Value = CE->getValue();
638 return Value >= 0 && Value < 32;
639 }
640 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000641 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000642 return false;
643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value > 0 && Value <= 32;
647 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000648 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000649 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000650 return false;
651 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
652 if (!CE) return false;
653 int64_t Value = CE->getValue();
654 return ARM_AM::getSOImmVal(Value) != -1;
655 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000656 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000657 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000658 return false;
659 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
660 if (!CE) return false;
661 int64_t Value = CE->getValue();
662 return ARM_AM::getT2SOImmVal(Value) != -1;
663 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000664 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000665 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000666 return false;
667 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
668 if (!CE) return false;
669 int64_t Value = CE->getValue();
670 return Value == 1 || Value == 0;
671 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000672 bool isReg() const { return Kind == k_Register; }
673 bool isRegList() const { return Kind == k_RegisterList; }
674 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
675 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
676 bool isToken() const { return Kind == k_Token; }
677 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
678 bool isMemory() const { return Kind == k_Memory; }
679 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
680 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
681 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
682 bool isRotImm() const { return Kind == k_RotateImmediate; }
683 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
684 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000685 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000686 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000687 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000688 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000689 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000690 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000691 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000692 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
693 (alignOK || Memory.Alignment == 0);
694 }
695 bool isAlignedMemory() const {
696 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000697 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000698 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000699 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000700 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000701 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000702 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000703 if (!Memory.OffsetImm) return true;
704 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000705 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000706 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000707 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000708 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000709 return false;
710 // Immediate offset in range [-4095, 4095].
711 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
712 if (!CE) return false;
713 int64_t Val = CE->getValue();
714 return Val > -4096 && Val < 4096;
715 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000716 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000717 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000718 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000719 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000720 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000721 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000722 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000723 if (!Memory.OffsetImm) return true;
724 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000725 return Val > -256 && Val < 256;
726 }
727 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000728 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000729 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000730 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000731 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
732 // Immediate offset in range [-255, 255].
733 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
734 if (!CE) return false;
735 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000736 // Special case, #-0 is INT32_MIN.
737 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000738 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000739 bool isAddrMode5() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000740 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000741 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000742 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000743 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000744 if (!Memory.OffsetImm) return true;
745 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000746 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
747 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000748 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000749 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000750 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000751 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000752 return false;
753 return true;
754 }
755 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000756 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000757 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
758 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000759 return false;
760 return true;
761 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000762 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000763 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000764 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000765 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000766 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000767 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000768 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
769 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000770 return false;
771 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000772 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000773 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000774 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000775 return false;
776 return true;
777 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000778 bool isMemThumbRR() const {
779 // Thumb reg+reg addressing is simple. Just two registers, a base and
780 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000781 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000782 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000783 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000784 return isARMLowRegister(Memory.BaseRegNum) &&
785 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000786 }
787 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000788 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000789 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000790 return false;
791 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000792 if (!Memory.OffsetImm) return true;
793 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000794 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
795 }
Jim Grosbach38466302011-08-19 18:55:51 +0000796 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000797 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000798 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000799 return false;
800 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000801 if (!Memory.OffsetImm) return true;
802 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000803 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
804 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000805 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000806 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000807 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000808 return false;
809 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000810 if (!Memory.OffsetImm) return true;
811 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000812 return Val >= 0 && Val <= 31;
813 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000814 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000815 if (!isMemory() || Memory.OffsetRegNum != 0 ||
816 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000817 return false;
818 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000819 if (!Memory.OffsetImm) return true;
820 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000821 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000822 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000823 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000824 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000825 return false;
826 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000827 if (!Memory.OffsetImm) return true;
828 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000829 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
830 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000831 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000832 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000833 return false;
834 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000835 if (!Memory.OffsetImm) return true;
836 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000837 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
838 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000839 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000840 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000841 return false;
842 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000843 if (!Memory.OffsetImm) return true;
844 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000845 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000846 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000847 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000848 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000849 return false;
850 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (!Memory.OffsetImm) return true;
852 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000853 return Val >= 0 && Val < 256;
854 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000855 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000856 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000857 return false;
858 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000859 if (!Memory.OffsetImm) return true;
860 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000861 return Val > -256 && Val < 0;
862 }
863 bool isMemUImm12Offset() const {
864 // If we have an immediate that's not a constant, treat it as a label
865 // reference needing a fixup. If it is a constant, it's something else
866 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000867 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000868 return true;
869
Jim Grosbach57dcb852011-10-11 17:29:55 +0000870 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000871 return false;
872 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000873 if (!Memory.OffsetImm) return true;
874 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000875 return (Val >= 0 && Val < 4096);
876 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000877 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000878 // If we have an immediate that's not a constant, treat it as a label
879 // reference needing a fixup. If it is a constant, it's something else
880 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000881 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000882 return true;
883
Jim Grosbach57dcb852011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000885 return false;
886 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000889 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000890 }
891 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000892 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000893 return false;
894 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
895 if (!CE) return false;
896 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000897 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000898 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000899 bool isPostIdxImm8s4() const {
900 if (Kind != k_Immediate)
901 return false;
902 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
903 if (!CE) return false;
904 int64_t Val = CE->getValue();
905 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
906 (Val == INT32_MIN);
907 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000908
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000909 bool isMSRMask() const { return Kind == k_MSRMask; }
910 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000911
Jim Grosbach0e387b22011-10-17 22:26:03 +0000912 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000913 bool isVecListOneD() const {
914 if (Kind != k_VectorList) return false;
915 return VectorList.Count == 1;
916 }
917
Jim Grosbach280dfad2011-10-21 18:54:25 +0000918 bool isVecListTwoD() const {
919 if (Kind != k_VectorList) return false;
920 return VectorList.Count == 2;
921 }
922
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000923 bool isVecListThreeD() const {
924 if (Kind != k_VectorList) return false;
925 return VectorList.Count == 3;
926 }
927
Jim Grosbachb6310312011-10-21 20:35:01 +0000928 bool isVecListFourD() const {
929 if (Kind != k_VectorList) return false;
930 return VectorList.Count == 4;
931 }
932
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000933 bool isVecListTwoQ() const {
934 if (Kind != k_VectorList) return false;
935 //FIXME: We haven't taught the parser to handle by-two register lists
936 // yet, so don't pretend to know one.
937 return VectorList.Count == 2 && false;
938 }
939
Jim Grosbach460a9052011-10-07 23:56:00 +0000940 bool isVectorIndex8() const {
941 if (Kind != k_VectorIndex) return false;
942 return VectorIndex.Val < 8;
943 }
944 bool isVectorIndex16() const {
945 if (Kind != k_VectorIndex) return false;
946 return VectorIndex.Val < 4;
947 }
948 bool isVectorIndex32() const {
949 if (Kind != k_VectorIndex) return false;
950 return VectorIndex.Val < 2;
951 }
952
Jim Grosbach0e387b22011-10-17 22:26:03 +0000953 bool isNEONi8splat() const {
954 if (Kind != k_Immediate)
955 return false;
956 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
957 // Must be a constant.
958 if (!CE) return false;
959 int64_t Value = CE->getValue();
960 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
961 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000962 return Value >= 0 && Value < 256;
963 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000964
Jim Grosbachea461102011-10-17 23:09:09 +0000965 bool isNEONi16splat() const {
966 if (Kind != k_Immediate)
967 return false;
968 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
969 // Must be a constant.
970 if (!CE) return false;
971 int64_t Value = CE->getValue();
972 // i16 value in the range [0,255] or [0x0100, 0xff00]
973 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
974 }
975
Jim Grosbach6248a542011-10-18 00:22:00 +0000976 bool isNEONi32splat() const {
977 if (Kind != k_Immediate)
978 return false;
979 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
980 // Must be a constant.
981 if (!CE) return false;
982 int64_t Value = CE->getValue();
983 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
984 return (Value >= 0 && Value < 256) ||
985 (Value >= 0x0100 && Value <= 0xff00) ||
986 (Value >= 0x010000 && Value <= 0xff0000) ||
987 (Value >= 0x01000000 && Value <= 0xff000000);
988 }
989
990 bool isNEONi32vmov() const {
991 if (Kind != k_Immediate)
992 return false;
993 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
994 // Must be a constant.
995 if (!CE) return false;
996 int64_t Value = CE->getValue();
997 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
998 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
999 return (Value >= 0 && Value < 256) ||
1000 (Value >= 0x0100 && Value <= 0xff00) ||
1001 (Value >= 0x010000 && Value <= 0xff0000) ||
1002 (Value >= 0x01000000 && Value <= 0xff000000) ||
1003 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1004 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1005 }
1006
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001007 bool isNEONi64splat() const {
1008 if (Kind != k_Immediate)
1009 return false;
1010 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1011 // Must be a constant.
1012 if (!CE) return false;
1013 uint64_t Value = CE->getValue();
1014 // i64 value with each byte being either 0 or 0xff.
1015 for (unsigned i = 0; i < 8; ++i)
1016 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1017 return true;
1018 }
1019
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001020 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001021 // Add as immediates when possible. Null MCExpr = 0.
1022 if (Expr == 0)
1023 Inst.addOperand(MCOperand::CreateImm(0));
1024 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001025 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1026 else
1027 Inst.addOperand(MCOperand::CreateExpr(Expr));
1028 }
1029
Daniel Dunbar8462b302010-08-11 06:36:53 +00001030 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001031 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001032 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001033 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1034 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001035 }
1036
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001037 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1038 assert(N == 1 && "Invalid number of operands!");
1039 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1040 }
1041
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001042 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1043 assert(N == 1 && "Invalid number of operands!");
1044 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1045 }
1046
1047 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1048 assert(N == 1 && "Invalid number of operands!");
1049 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1050 }
1051
Jim Grosbach89df9962011-08-26 21:43:41 +00001052 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1053 assert(N == 1 && "Invalid number of operands!");
1054 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1055 }
1056
1057 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1058 assert(N == 1 && "Invalid number of operands!");
1059 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1060 }
1061
Jim Grosbachd67641b2010-12-06 18:21:12 +00001062 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
1064 Inst.addOperand(MCOperand::CreateReg(getReg()));
1065 }
1066
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001067 void addRegOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
1069 Inst.addOperand(MCOperand::CreateReg(getReg()));
1070 }
1071
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001072 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001073 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001074 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1075 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1076 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001077 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001078 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001079 }
1080
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001081 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001082 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001083 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1084 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001085 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001086 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001087 }
1088
Jim Grosbach580f4a92011-07-25 22:20:28 +00001089 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001090 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001091 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1092 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001093 }
1094
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001095 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001096 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001097 const SmallVectorImpl<unsigned> &RegList = getRegList();
1098 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001099 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1100 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001101 }
1102
Bill Wendling0f630752010-11-17 04:32:08 +00001103 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1104 addRegListOperands(Inst, N);
1105 }
1106
1107 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1108 addRegListOperands(Inst, N);
1109 }
1110
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001111 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
1113 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1114 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1115 }
1116
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001117 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
1119 // Munge the lsb/width into a bitfield mask.
1120 unsigned lsb = Bitfield.LSB;
1121 unsigned width = Bitfield.Width;
1122 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1123 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1124 (32 - (lsb + width)));
1125 Inst.addOperand(MCOperand::CreateImm(Mask));
1126 }
1127
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001128 void addImmOperands(MCInst &Inst, unsigned N) const {
1129 assert(N == 1 && "Invalid number of operands!");
1130 addExpr(Inst, getImm());
1131 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001132
Jim Grosbach9d390362011-10-03 23:38:36 +00001133 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1134 assert(N == 1 && "Invalid number of operands!");
1135 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1136 }
1137
Jim Grosbacha77295d2011-09-08 22:07:06 +00001138 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1139 assert(N == 1 && "Invalid number of operands!");
1140 // FIXME: We really want to scale the value here, but the LDRD/STRD
1141 // instruction don't encode operands that way yet.
1142 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1143 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1144 }
1145
Jim Grosbach72f39f82011-08-24 21:22:15 +00001146 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1147 assert(N == 1 && "Invalid number of operands!");
1148 // The immediate is scaled by four in the encoding and is stored
1149 // in the MCInst as such. Lop off the low two bits here.
1150 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1151 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1152 }
1153
1154 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1155 assert(N == 1 && "Invalid number of operands!");
1156 // The immediate is scaled by four in the encoding and is stored
1157 // in the MCInst as such. Lop off the low two bits here.
1158 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1159 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1160 }
1161
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001162 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1163 assert(N == 1 && "Invalid number of operands!");
1164 addExpr(Inst, getImm());
1165 }
1166
Jim Grosbach83ab0702011-07-13 22:01:08 +00001167 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1168 assert(N == 1 && "Invalid number of operands!");
1169 addExpr(Inst, getImm());
1170 }
1171
1172 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1173 assert(N == 1 && "Invalid number of operands!");
1174 addExpr(Inst, getImm());
1175 }
1176
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001177 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1178 assert(N == 1 && "Invalid number of operands!");
1179 addExpr(Inst, getImm());
1180 }
1181
Jim Grosbachf4943352011-07-25 23:09:14 +00001182 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1183 assert(N == 1 && "Invalid number of operands!");
1184 // The constant encodes as the immediate-1, and we store in the instruction
1185 // the bits as encoded, so subtract off one here.
1186 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1187 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1188 }
1189
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001190 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1191 assert(N == 1 && "Invalid number of operands!");
1192 // The constant encodes as the immediate-1, and we store in the instruction
1193 // the bits as encoded, so subtract off one here.
1194 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1195 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1196 }
1197
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001198 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1199 assert(N == 1 && "Invalid number of operands!");
1200 addExpr(Inst, getImm());
1201 }
1202
Jim Grosbachffa32252011-07-19 19:13:28 +00001203 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1204 assert(N == 1 && "Invalid number of operands!");
1205 addExpr(Inst, getImm());
1206 }
1207
Jim Grosbached838482011-07-26 16:24:27 +00001208 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1209 assert(N == 1 && "Invalid number of operands!");
1210 addExpr(Inst, getImm());
1211 }
1212
Jim Grosbach70939ee2011-08-17 21:51:27 +00001213 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 1 && "Invalid number of operands!");
1215 // The constant encodes as the immediate, except for 32, which encodes as
1216 // zero.
1217 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1218 unsigned Imm = CE->getValue();
1219 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1220 }
1221
Jim Grosbachf6c05252011-07-21 17:23:04 +00001222 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1223 assert(N == 1 && "Invalid number of operands!");
1224 addExpr(Inst, getImm());
1225 }
1226
1227 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1228 assert(N == 1 && "Invalid number of operands!");
1229 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1230 // the instruction as well.
1231 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1232 int Val = CE->getValue();
1233 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1234 }
1235
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001236 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 addExpr(Inst, getImm());
1239 }
1240
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001241 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1242 assert(N == 1 && "Invalid number of operands!");
1243 addExpr(Inst, getImm());
1244 }
1245
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001246 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1247 assert(N == 1 && "Invalid number of operands!");
1248 addExpr(Inst, getImm());
1249 }
1250
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001251 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1252 assert(N == 1 && "Invalid number of operands!");
1253 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1254 }
1255
Jim Grosbach7ce05792011-08-03 23:50:40 +00001256 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1257 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001258 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001259 }
1260
Jim Grosbach57dcb852011-10-11 17:29:55 +00001261 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1262 assert(N == 2 && "Invalid number of operands!");
1263 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1264 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1265 }
1266
Jim Grosbach7ce05792011-08-03 23:50:40 +00001267 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1268 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001269 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1270 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001271 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1272 // Special case for #-0
1273 if (Val == INT32_MIN) Val = 0;
1274 if (Val < 0) Val = -Val;
1275 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1276 } else {
1277 // For register offset, we encode the shift type and negation flag
1278 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001279 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1280 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001281 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001282 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1283 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001284 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001285 }
1286
Jim Grosbach039c2e12011-08-04 23:01:30 +00001287 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1288 assert(N == 2 && "Invalid number of operands!");
1289 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1290 assert(CE && "non-constant AM2OffsetImm operand!");
1291 int32_t Val = CE->getValue();
1292 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1293 // Special case for #-0
1294 if (Val == INT32_MIN) Val = 0;
1295 if (Val < 0) Val = -Val;
1296 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1297 Inst.addOperand(MCOperand::CreateReg(0));
1298 Inst.addOperand(MCOperand::CreateImm(Val));
1299 }
1300
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001301 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1302 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001303 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1304 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001305 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1306 // Special case for #-0
1307 if (Val == INT32_MIN) Val = 0;
1308 if (Val < 0) Val = -Val;
1309 Val = ARM_AM::getAM3Opc(AddSub, Val);
1310 } else {
1311 // For register offset, we encode the shift type and negation flag
1312 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001313 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001314 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001315 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1316 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001317 Inst.addOperand(MCOperand::CreateImm(Val));
1318 }
1319
1320 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1321 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001322 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001323 int32_t Val =
1324 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1325 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1326 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001327 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001328 }
1329
1330 // Constant offset.
1331 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1332 int32_t Val = CE->getValue();
1333 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1334 // Special case for #-0
1335 if (Val == INT32_MIN) Val = 0;
1336 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001337 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001338 Inst.addOperand(MCOperand::CreateReg(0));
1339 Inst.addOperand(MCOperand::CreateImm(Val));
1340 }
1341
Jim Grosbach7ce05792011-08-03 23:50:40 +00001342 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1343 assert(N == 2 && "Invalid number of operands!");
1344 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001345 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001346 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1347 // Special case for #-0
1348 if (Val == INT32_MIN) Val = 0;
1349 if (Val < 0) Val = -Val;
1350 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001351 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001352 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001353 }
1354
Jim Grosbacha77295d2011-09-08 22:07:06 +00001355 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1356 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001357 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1358 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001359 Inst.addOperand(MCOperand::CreateImm(Val));
1360 }
1361
Jim Grosbachb6aed502011-09-09 18:37:27 +00001362 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1363 assert(N == 2 && "Invalid number of operands!");
1364 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001365 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1366 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001367 Inst.addOperand(MCOperand::CreateImm(Val));
1368 }
1369
Jim Grosbach7ce05792011-08-03 23:50:40 +00001370 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1371 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001372 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1373 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001374 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001375 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001376
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001377 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1378 addMemImm8OffsetOperands(Inst, N);
1379 }
1380
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001381 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001382 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001383 }
1384
1385 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 2 && "Invalid number of operands!");
1387 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001388 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001389 addExpr(Inst, getImm());
1390 Inst.addOperand(MCOperand::CreateImm(0));
1391 return;
1392 }
1393
1394 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001395 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1396 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001397 Inst.addOperand(MCOperand::CreateImm(Val));
1398 }
1399
Jim Grosbach7ce05792011-08-03 23:50:40 +00001400 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1401 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001402 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001403 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001404 addExpr(Inst, getImm());
1405 Inst.addOperand(MCOperand::CreateImm(0));
1406 return;
1407 }
1408
1409 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001410 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1411 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001412 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001413 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001414
Jim Grosbach7f739be2011-09-19 22:21:13 +00001415 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1416 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001417 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1418 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001419 }
1420
1421 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1422 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001423 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1424 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001425 }
1426
Jim Grosbach7ce05792011-08-03 23:50:40 +00001427 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1428 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001429 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1430 Memory.ShiftImm, Memory.ShiftType);
1431 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1432 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001433 Inst.addOperand(MCOperand::CreateImm(Val));
1434 }
1435
Jim Grosbachab899c12011-09-07 23:10:15 +00001436 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001438 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1439 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1440 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001441 }
1442
Jim Grosbach7ce05792011-08-03 23:50:40 +00001443 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1444 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001445 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1446 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001447 }
1448
Jim Grosbach60f91a32011-08-19 17:55:24 +00001449 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1450 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001451 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1452 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001453 Inst.addOperand(MCOperand::CreateImm(Val));
1454 }
1455
Jim Grosbach38466302011-08-19 18:55:51 +00001456 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1457 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001458 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1459 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001460 Inst.addOperand(MCOperand::CreateImm(Val));
1461 }
1462
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001463 void addMemThumbRIs1Operands(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()) : 0;
1466 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001467 Inst.addOperand(MCOperand::CreateImm(Val));
1468 }
1469
Jim Grosbachecd85892011-08-19 18:13:48 +00001470 void addMemThumbSPIOperands(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() / 4) : 0;
1473 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001474 Inst.addOperand(MCOperand::CreateImm(Val));
1475 }
1476
Jim Grosbach7ce05792011-08-03 23:50:40 +00001477 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1480 assert(CE && "non-constant post-idx-imm8 operand!");
1481 int Imm = CE->getValue();
1482 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001483 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001484 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1485 Inst.addOperand(MCOperand::CreateImm(Imm));
1486 }
1487
Jim Grosbach2bd01182011-10-11 21:55:36 +00001488 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
1490 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1491 assert(CE && "non-constant post-idx-imm8s4 operand!");
1492 int Imm = CE->getValue();
1493 bool isAdd = Imm >= 0;
1494 if (Imm == INT32_MIN) Imm = 0;
1495 // Immediate is scaled by 4.
1496 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1497 Inst.addOperand(MCOperand::CreateImm(Imm));
1498 }
1499
Jim Grosbach7ce05792011-08-03 23:50:40 +00001500 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1501 assert(N == 2 && "Invalid number of operands!");
1502 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001503 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1504 }
1505
1506 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 2 && "Invalid number of operands!");
1508 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1509 // The sign, shift type, and shift amount are encoded in a single operand
1510 // using the AM2 encoding helpers.
1511 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1512 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1513 PostIdxReg.ShiftTy);
1514 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001515 }
1516
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001517 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 1 && "Invalid number of operands!");
1519 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1520 }
1521
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001522 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1525 }
1526
Jim Grosbach862019c2011-10-18 23:02:30 +00001527 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1528 assert(N == 1 && "Invalid number of operands!");
1529 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1530 }
1531
Jim Grosbach280dfad2011-10-21 18:54:25 +00001532 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534 // Only the first register actually goes on the instruction. The rest
1535 // are implied by the opcode.
1536 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1537 }
1538
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001539 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 1 && "Invalid number of operands!");
1541 // Only the first register actually goes on the instruction. The rest
1542 // are implied by the opcode.
1543 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1544 }
1545
Jim Grosbachb6310312011-10-21 20:35:01 +00001546 void addVecListFourDOperands(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 Grosbach4661d4c2011-10-21 22:21:10 +00001553 void addVecListTwoQOperands(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 Grosbach460a9052011-10-07 23:56:00 +00001560 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1563 }
1564
1565 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1568 }
1569
1570 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1571 assert(N == 1 && "Invalid number of operands!");
1572 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1573 }
1574
Jim Grosbach0e387b22011-10-17 22:26:03 +00001575 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577 // The immediate encodes the type of constant as well as the value.
1578 // Mask in that this is an i8 splat.
1579 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1580 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1581 }
1582
Jim Grosbachea461102011-10-17 23:09:09 +00001583 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 1 && "Invalid number of operands!");
1585 // The immediate encodes the type of constant as well as the value.
1586 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1587 unsigned Value = CE->getValue();
1588 if (Value >= 256)
1589 Value = (Value >> 8) | 0xa00;
1590 else
1591 Value |= 0x800;
1592 Inst.addOperand(MCOperand::CreateImm(Value));
1593 }
1594
Jim Grosbach6248a542011-10-18 00:22:00 +00001595 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1596 assert(N == 1 && "Invalid number of operands!");
1597 // The immediate encodes the type of constant as well as the value.
1598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1599 unsigned Value = CE->getValue();
1600 if (Value >= 256 && Value <= 0xff00)
1601 Value = (Value >> 8) | 0x200;
1602 else if (Value > 0xffff && Value <= 0xff0000)
1603 Value = (Value >> 16) | 0x400;
1604 else if (Value > 0xffffff)
1605 Value = (Value >> 24) | 0x600;
1606 Inst.addOperand(MCOperand::CreateImm(Value));
1607 }
1608
1609 void addNEONi32vmovOperands(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 <= 0xffff)
1615 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1616 else if (Value > 0xffff && Value <= 0xffffff)
1617 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1618 else if (Value > 0xffffff)
1619 Value = (Value >> 24) | 0x600;
1620 Inst.addOperand(MCOperand::CreateImm(Value));
1621 }
1622
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001623 void addNEONi64splatOperands(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 uint64_t Value = CE->getValue();
1628 unsigned Imm = 0;
1629 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1630 Imm |= (Value & 1) << i;
1631 }
1632 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1633 }
1634
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001635 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001636
Jim Grosbach89df9962011-08-26 21:43:41 +00001637 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001638 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001639 Op->ITMask.Mask = Mask;
1640 Op->StartLoc = S;
1641 Op->EndLoc = S;
1642 return Op;
1643 }
1644
Chris Lattner3a697562010-10-28 17:20:03 +00001645 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001646 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001647 Op->CC.Val = CC;
1648 Op->StartLoc = S;
1649 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001650 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001651 }
1652
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001653 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001654 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001655 Op->Cop.Val = CopVal;
1656 Op->StartLoc = S;
1657 Op->EndLoc = S;
1658 return Op;
1659 }
1660
1661 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001662 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001663 Op->Cop.Val = CopVal;
1664 Op->StartLoc = S;
1665 Op->EndLoc = S;
1666 return Op;
1667 }
1668
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001669 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1670 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1671 Op->Cop.Val = Val;
1672 Op->StartLoc = S;
1673 Op->EndLoc = E;
1674 return Op;
1675 }
1676
Jim Grosbachd67641b2010-12-06 18:21:12 +00001677 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001678 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001679 Op->Reg.RegNum = RegNum;
1680 Op->StartLoc = S;
1681 Op->EndLoc = S;
1682 return Op;
1683 }
1684
Chris Lattner3a697562010-10-28 17:20:03 +00001685 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001686 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001687 Op->Tok.Data = Str.data();
1688 Op->Tok.Length = Str.size();
1689 Op->StartLoc = S;
1690 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001691 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001692 }
1693
Bill Wendling50d0f582010-11-18 23:43:05 +00001694 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001695 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001696 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001697 Op->StartLoc = S;
1698 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001699 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001700 }
1701
Jim Grosbache8606dc2011-07-13 17:50:29 +00001702 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1703 unsigned SrcReg,
1704 unsigned ShiftReg,
1705 unsigned ShiftImm,
1706 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001707 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001708 Op->RegShiftedReg.ShiftTy = ShTy;
1709 Op->RegShiftedReg.SrcReg = SrcReg;
1710 Op->RegShiftedReg.ShiftReg = ShiftReg;
1711 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001712 Op->StartLoc = S;
1713 Op->EndLoc = E;
1714 return Op;
1715 }
1716
Owen Anderson92a20222011-07-21 18:54:16 +00001717 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1718 unsigned SrcReg,
1719 unsigned ShiftImm,
1720 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001721 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001722 Op->RegShiftedImm.ShiftTy = ShTy;
1723 Op->RegShiftedImm.SrcReg = SrcReg;
1724 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001725 Op->StartLoc = S;
1726 Op->EndLoc = E;
1727 return Op;
1728 }
1729
Jim Grosbach580f4a92011-07-25 22:20:28 +00001730 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001731 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001732 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001733 Op->ShifterImm.isASR = isASR;
1734 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001735 Op->StartLoc = S;
1736 Op->EndLoc = E;
1737 return Op;
1738 }
1739
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001740 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001741 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001742 Op->RotImm.Imm = Imm;
1743 Op->StartLoc = S;
1744 Op->EndLoc = E;
1745 return Op;
1746 }
1747
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001748 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1749 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001750 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001751 Op->Bitfield.LSB = LSB;
1752 Op->Bitfield.Width = Width;
1753 Op->StartLoc = S;
1754 Op->EndLoc = E;
1755 return Op;
1756 }
1757
Bill Wendling7729e062010-11-09 22:44:22 +00001758 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001759 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001760 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001761 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001762
Jim Grosbachd300b942011-09-13 22:56:44 +00001763 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001764 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001765 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001766 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001767 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001768
1769 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001770 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001771 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001772 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001773 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001774 Op->StartLoc = StartLoc;
1775 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001776 return Op;
1777 }
1778
Jim Grosbach862019c2011-10-18 23:02:30 +00001779 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1780 SMLoc S, SMLoc E) {
1781 ARMOperand *Op = new ARMOperand(k_VectorList);
1782 Op->VectorList.RegNum = RegNum;
1783 Op->VectorList.Count = Count;
1784 Op->StartLoc = S;
1785 Op->EndLoc = E;
1786 return Op;
1787 }
1788
Jim Grosbach460a9052011-10-07 23:56:00 +00001789 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1790 MCContext &Ctx) {
1791 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1792 Op->VectorIndex.Val = Idx;
1793 Op->StartLoc = S;
1794 Op->EndLoc = E;
1795 return Op;
1796 }
1797
Chris Lattner3a697562010-10-28 17:20:03 +00001798 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001799 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001800 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001801 Op->StartLoc = S;
1802 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001803 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001804 }
1805
Jim Grosbach9d390362011-10-03 23:38:36 +00001806 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001807 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001808 Op->FPImm.Val = Val;
1809 Op->StartLoc = S;
1810 Op->EndLoc = S;
1811 return Op;
1812 }
1813
Jim Grosbach7ce05792011-08-03 23:50:40 +00001814 static ARMOperand *CreateMem(unsigned BaseRegNum,
1815 const MCConstantExpr *OffsetImm,
1816 unsigned OffsetRegNum,
1817 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001818 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001819 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001820 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001821 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001822 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001823 Op->Memory.BaseRegNum = BaseRegNum;
1824 Op->Memory.OffsetImm = OffsetImm;
1825 Op->Memory.OffsetRegNum = OffsetRegNum;
1826 Op->Memory.ShiftType = ShiftType;
1827 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001828 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001829 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001830 Op->StartLoc = S;
1831 Op->EndLoc = E;
1832 return Op;
1833 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001834
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001835 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1836 ARM_AM::ShiftOpc ShiftTy,
1837 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001838 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001839 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001840 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001841 Op->PostIdxReg.isAdd = isAdd;
1842 Op->PostIdxReg.ShiftTy = ShiftTy;
1843 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001844 Op->StartLoc = S;
1845 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001846 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001847 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001848
1849 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001850 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001851 Op->MBOpt.Val = Opt;
1852 Op->StartLoc = S;
1853 Op->EndLoc = S;
1854 return Op;
1855 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001856
1857 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001858 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001859 Op->IFlags.Val = IFlags;
1860 Op->StartLoc = S;
1861 Op->EndLoc = S;
1862 return Op;
1863 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001864
1865 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001866 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001867 Op->MMask.Val = MMask;
1868 Op->StartLoc = S;
1869 Op->EndLoc = S;
1870 return Op;
1871 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001872};
1873
1874} // end anonymous namespace.
1875
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001876void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001877 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001878 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001879 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1880 << ") >";
1881 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001882 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001883 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001884 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001885 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001886 OS << "<ccout " << getReg() << ">";
1887 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001888 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001889 static const char *MaskStr[] = {
1890 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1891 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1892 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001893 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1894 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1895 break;
1896 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001897 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001898 OS << "<coprocessor number: " << getCoproc() << ">";
1899 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001900 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001901 OS << "<coprocessor register: " << getCoproc() << ">";
1902 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001903 case k_CoprocOption:
1904 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1905 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001906 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001907 OS << "<mask: " << getMSRMask() << ">";
1908 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001909 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001910 getImm()->print(OS);
1911 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001912 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001913 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1914 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001916 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001917 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001918 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001919 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001920 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001921 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1922 << PostIdxReg.RegNum;
1923 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1924 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1925 << PostIdxReg.ShiftImm;
1926 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001927 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001928 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001929 OS << "<ARM_PROC::";
1930 unsigned IFlags = getProcIFlags();
1931 for (int i=2; i >= 0; --i)
1932 if (IFlags & (1 << i))
1933 OS << ARM_PROC::IFlagsToString(1 << i);
1934 OS << ">";
1935 break;
1936 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001937 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001938 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001939 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001940 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001941 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1942 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001943 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001944 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001945 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001946 << RegShiftedReg.SrcReg
1947 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1948 << ", " << RegShiftedReg.ShiftReg << ", "
1949 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001950 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001951 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001952 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001953 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001954 << RegShiftedImm.SrcReg
1955 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1956 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001957 << ">";
1958 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001959 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001960 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1961 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001962 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001963 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1964 << ", width: " << Bitfield.Width << ">";
1965 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001966 case k_RegisterList:
1967 case k_DPRRegisterList:
1968 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001969 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001970
Bill Wendling5fa22a12010-11-09 23:28:44 +00001971 const SmallVectorImpl<unsigned> &RegList = getRegList();
1972 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001973 I = RegList.begin(), E = RegList.end(); I != E; ) {
1974 OS << *I;
1975 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001976 }
1977
1978 OS << ">";
1979 break;
1980 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001981 case k_VectorList:
1982 OS << "<vector_list " << VectorList.Count << " * "
1983 << VectorList.RegNum << ">";
1984 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001985 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001986 OS << "'" << getToken() << "'";
1987 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001988 case k_VectorIndex:
1989 OS << "<vectorindex " << getVectorIndex() << ">";
1990 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001991 }
1992}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001993
1994/// @name Auto-generated Match Functions
1995/// {
1996
1997static unsigned MatchRegisterName(StringRef Name);
1998
1999/// }
2000
Bob Wilson69df7232011-02-03 21:46:10 +00002001bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2002 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002003 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002004
2005 return (RegNo == (unsigned)-1);
2006}
2007
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002008/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002009/// and if it is a register name the token is eaten and the register number is
2010/// returned. Otherwise return -1.
2011///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002012int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002013 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002014 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002015
Chris Lattnere5658fa2010-10-30 04:09:10 +00002016 // FIXME: Validate register for the current architecture; we have to do
2017 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00002018 std::string upperCase = Tok.getString().str();
2019 std::string lowerCase = LowercaseString(upperCase);
2020 unsigned RegNum = MatchRegisterName(lowerCase);
2021 if (!RegNum) {
2022 RegNum = StringSwitch<unsigned>(lowerCase)
2023 .Case("r13", ARM::SP)
2024 .Case("r14", ARM::LR)
2025 .Case("r15", ARM::PC)
2026 .Case("ip", ARM::R12)
2027 .Default(0);
2028 }
2029 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002030
Chris Lattnere5658fa2010-10-30 04:09:10 +00002031 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002032
Chris Lattnere5658fa2010-10-30 04:09:10 +00002033 return RegNum;
2034}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002035
Jim Grosbach19906722011-07-13 18:49:30 +00002036// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2037// If a recoverable error occurs, return 1. If an irrecoverable error
2038// occurs, return -1. An irrecoverable error is one where tokens have been
2039// consumed in the process of trying to parse the shifter (i.e., when it is
2040// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002041int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002042 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2043 SMLoc S = Parser.getTok().getLoc();
2044 const AsmToken &Tok = Parser.getTok();
2045 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2046
2047 std::string upperCase = Tok.getString().str();
2048 std::string lowerCase = LowercaseString(upperCase);
2049 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2050 .Case("lsl", ARM_AM::lsl)
2051 .Case("lsr", ARM_AM::lsr)
2052 .Case("asr", ARM_AM::asr)
2053 .Case("ror", ARM_AM::ror)
2054 .Case("rrx", ARM_AM::rrx)
2055 .Default(ARM_AM::no_shift);
2056
2057 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002058 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002059
Jim Grosbache8606dc2011-07-13 17:50:29 +00002060 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002061
Jim Grosbache8606dc2011-07-13 17:50:29 +00002062 // The source register for the shift has already been added to the
2063 // operand list, so we need to pop it off and combine it into the shifted
2064 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002065 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002066 if (!PrevOp->isReg())
2067 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2068 int SrcReg = PrevOp->getReg();
2069 int64_t Imm = 0;
2070 int ShiftReg = 0;
2071 if (ShiftTy == ARM_AM::rrx) {
2072 // RRX Doesn't have an explicit shift amount. The encoder expects
2073 // the shift register to be the same as the source register. Seems odd,
2074 // but OK.
2075 ShiftReg = SrcReg;
2076 } else {
2077 // Figure out if this is shifted by a constant or a register (for non-RRX).
2078 if (Parser.getTok().is(AsmToken::Hash)) {
2079 Parser.Lex(); // Eat hash.
2080 SMLoc ImmLoc = Parser.getTok().getLoc();
2081 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002082 if (getParser().ParseExpression(ShiftExpr)) {
2083 Error(ImmLoc, "invalid immediate shift value");
2084 return -1;
2085 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002086 // The expression must be evaluatable as an immediate.
2087 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002088 if (!CE) {
2089 Error(ImmLoc, "invalid immediate shift value");
2090 return -1;
2091 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002092 // Range check the immediate.
2093 // lsl, ror: 0 <= imm <= 31
2094 // lsr, asr: 0 <= imm <= 32
2095 Imm = CE->getValue();
2096 if (Imm < 0 ||
2097 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2098 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002099 Error(ImmLoc, "immediate shift value out of range");
2100 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002101 }
2102 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002103 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002104 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002105 if (ShiftReg == -1) {
2106 Error (L, "expected immediate or register in shift operand");
2107 return -1;
2108 }
2109 } else {
2110 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002111 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002112 return -1;
2113 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002114 }
2115
Owen Anderson92a20222011-07-21 18:54:16 +00002116 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2117 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002118 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002119 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002120 else
2121 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2122 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002123
Jim Grosbach19906722011-07-13 18:49:30 +00002124 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002125}
2126
2127
Bill Wendling50d0f582010-11-18 23:43:05 +00002128/// Try to parse a register name. The token must be an Identifier when called.
2129/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2130/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002131///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002132/// TODO this is likely to change to allow different register types and or to
2133/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002134bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002135tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002136 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002137 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002138 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002139 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002140
Bill Wendling50d0f582010-11-18 23:43:05 +00002141 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002142
Chris Lattnere5658fa2010-10-30 04:09:10 +00002143 const AsmToken &ExclaimTok = Parser.getTok();
2144 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002145 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2146 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002147 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002148 return false;
2149 }
2150
2151 // Also check for an index operand. This is only legal for vector registers,
2152 // but that'll get caught OK in operand matching, so we don't need to
2153 // explicitly filter everything else out here.
2154 if (Parser.getTok().is(AsmToken::LBrac)) {
2155 SMLoc SIdx = Parser.getTok().getLoc();
2156 Parser.Lex(); // Eat left bracket token.
2157
2158 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002159 if (getParser().ParseExpression(ImmVal))
2160 return MatchOperand_ParseFail;
2161 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2162 if (!MCE) {
2163 TokError("immediate value expected for vector index");
2164 return MatchOperand_ParseFail;
2165 }
2166
2167 SMLoc E = Parser.getTok().getLoc();
2168 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2169 Error(E, "']' expected");
2170 return MatchOperand_ParseFail;
2171 }
2172
2173 Parser.Lex(); // Eat right bracket token.
2174
2175 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2176 SIdx, E,
2177 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002178 }
2179
Bill Wendling50d0f582010-11-18 23:43:05 +00002180 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002181}
2182
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002183/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2184/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2185/// "c5", ...
2186static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002187 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2188 // but efficient.
2189 switch (Name.size()) {
2190 default: break;
2191 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002192 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002193 return -1;
2194 switch (Name[1]) {
2195 default: return -1;
2196 case '0': return 0;
2197 case '1': return 1;
2198 case '2': return 2;
2199 case '3': return 3;
2200 case '4': return 4;
2201 case '5': return 5;
2202 case '6': return 6;
2203 case '7': return 7;
2204 case '8': return 8;
2205 case '9': return 9;
2206 }
2207 break;
2208 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002209 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002210 return -1;
2211 switch (Name[2]) {
2212 default: return -1;
2213 case '0': return 10;
2214 case '1': return 11;
2215 case '2': return 12;
2216 case '3': return 13;
2217 case '4': return 14;
2218 case '5': return 15;
2219 }
2220 break;
2221 }
2222
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002223 return -1;
2224}
2225
Jim Grosbach89df9962011-08-26 21:43:41 +00002226/// parseITCondCode - Try to parse a condition code for an IT instruction.
2227ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2228parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2229 SMLoc S = Parser.getTok().getLoc();
2230 const AsmToken &Tok = Parser.getTok();
2231 if (!Tok.is(AsmToken::Identifier))
2232 return MatchOperand_NoMatch;
2233 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2234 .Case("eq", ARMCC::EQ)
2235 .Case("ne", ARMCC::NE)
2236 .Case("hs", ARMCC::HS)
2237 .Case("cs", ARMCC::HS)
2238 .Case("lo", ARMCC::LO)
2239 .Case("cc", ARMCC::LO)
2240 .Case("mi", ARMCC::MI)
2241 .Case("pl", ARMCC::PL)
2242 .Case("vs", ARMCC::VS)
2243 .Case("vc", ARMCC::VC)
2244 .Case("hi", ARMCC::HI)
2245 .Case("ls", ARMCC::LS)
2246 .Case("ge", ARMCC::GE)
2247 .Case("lt", ARMCC::LT)
2248 .Case("gt", ARMCC::GT)
2249 .Case("le", ARMCC::LE)
2250 .Case("al", ARMCC::AL)
2251 .Default(~0U);
2252 if (CC == ~0U)
2253 return MatchOperand_NoMatch;
2254 Parser.Lex(); // Eat the token.
2255
2256 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2257
2258 return MatchOperand_Success;
2259}
2260
Jim Grosbach43904292011-07-25 20:14:50 +00002261/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002262/// token must be an Identifier when called, and if it is a coprocessor
2263/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002264ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002265parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002266 SMLoc S = Parser.getTok().getLoc();
2267 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002268 if (Tok.isNot(AsmToken::Identifier))
2269 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002270
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002271 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002272 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002273 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002274
2275 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002276 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002277 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002278}
2279
Jim Grosbach43904292011-07-25 20:14:50 +00002280/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002281/// token must be an Identifier when called, and if it is a coprocessor
2282/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002283ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002284parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002285 SMLoc S = Parser.getTok().getLoc();
2286 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002287 if (Tok.isNot(AsmToken::Identifier))
2288 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002289
2290 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2291 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002292 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002293
2294 Parser.Lex(); // Eat identifier token.
2295 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002296 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002297}
2298
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002299/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2300/// coproc_option : '{' imm0_255 '}'
2301ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2302parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2303 SMLoc S = Parser.getTok().getLoc();
2304
2305 // If this isn't a '{', this isn't a coprocessor immediate operand.
2306 if (Parser.getTok().isNot(AsmToken::LCurly))
2307 return MatchOperand_NoMatch;
2308 Parser.Lex(); // Eat the '{'
2309
2310 const MCExpr *Expr;
2311 SMLoc Loc = Parser.getTok().getLoc();
2312 if (getParser().ParseExpression(Expr)) {
2313 Error(Loc, "illegal expression");
2314 return MatchOperand_ParseFail;
2315 }
2316 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2317 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2318 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2319 return MatchOperand_ParseFail;
2320 }
2321 int Val = CE->getValue();
2322
2323 // Check for and consume the closing '}'
2324 if (Parser.getTok().isNot(AsmToken::RCurly))
2325 return MatchOperand_ParseFail;
2326 SMLoc E = Parser.getTok().getLoc();
2327 Parser.Lex(); // Eat the '}'
2328
2329 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2330 return MatchOperand_Success;
2331}
2332
Jim Grosbachd0588e22011-09-14 18:08:35 +00002333// For register list parsing, we need to map from raw GPR register numbering
2334// to the enumeration values. The enumeration values aren't sorted by
2335// register number due to our using "sp", "lr" and "pc" as canonical names.
2336static unsigned getNextRegister(unsigned Reg) {
2337 // If this is a GPR, we need to do it manually, otherwise we can rely
2338 // on the sort ordering of the enumeration since the other reg-classes
2339 // are sane.
2340 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2341 return Reg + 1;
2342 switch(Reg) {
2343 default: assert(0 && "Invalid GPR number!");
2344 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2345 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2346 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2347 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2348 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2349 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2350 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2351 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2352 }
2353}
2354
2355/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002356bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002357parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002358 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002359 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002360 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002361 Parser.Lex(); // Eat '{' token.
2362 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002363
Jim Grosbachd0588e22011-09-14 18:08:35 +00002364 // Check the first register in the list to see what register class
2365 // this is a list of.
2366 int Reg = tryParseRegister();
2367 if (Reg == -1)
2368 return Error(RegLoc, "register expected");
2369
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002370 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002371 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2372 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2373 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2374 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2375 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2376 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2377 else
2378 return Error(RegLoc, "invalid register in register list");
2379
2380 // The reglist instructions have at most 16 registers, so reserve
2381 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002382 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002383 // Store the first register.
2384 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002385
Jim Grosbachd0588e22011-09-14 18:08:35 +00002386 // This starts immediately after the first register token in the list,
2387 // so we can see either a comma or a minus (range separator) as a legal
2388 // next token.
2389 while (Parser.getTok().is(AsmToken::Comma) ||
2390 Parser.getTok().is(AsmToken::Minus)) {
2391 if (Parser.getTok().is(AsmToken::Minus)) {
2392 Parser.Lex(); // Eat the comma.
2393 SMLoc EndLoc = Parser.getTok().getLoc();
2394 int EndReg = tryParseRegister();
2395 if (EndReg == -1)
2396 return Error(EndLoc, "register expected");
2397 // If the register is the same as the start reg, there's nothing
2398 // more to do.
2399 if (Reg == EndReg)
2400 continue;
2401 // The register must be in the same register class as the first.
2402 if (!RC->contains(EndReg))
2403 return Error(EndLoc, "invalid register in register list");
2404 // Ranges must go from low to high.
2405 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2406 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002407
Jim Grosbachd0588e22011-09-14 18:08:35 +00002408 // Add all the registers in the range to the register list.
2409 while (Reg != EndReg) {
2410 Reg = getNextRegister(Reg);
2411 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2412 }
2413 continue;
2414 }
2415 Parser.Lex(); // Eat the comma.
2416 RegLoc = Parser.getTok().getLoc();
2417 int OldReg = Reg;
2418 Reg = tryParseRegister();
2419 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002420 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002421 // The register must be in the same register class as the first.
2422 if (!RC->contains(Reg))
2423 return Error(RegLoc, "invalid register in register list");
2424 // List must be monotonically increasing.
2425 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2426 return Error(RegLoc, "register list not in ascending order");
2427 // VFP register lists must also be contiguous.
2428 // It's OK to use the enumeration values directly here rather, as the
2429 // VFP register classes have the enum sorted properly.
2430 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2431 Reg != OldReg + 1)
2432 return Error(RegLoc, "non-contiguous register range");
2433 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002434 }
2435
Jim Grosbachd0588e22011-09-14 18:08:35 +00002436 SMLoc E = Parser.getTok().getLoc();
2437 if (Parser.getTok().isNot(AsmToken::RCurly))
2438 return Error(E, "'}' expected");
2439 Parser.Lex(); // Eat '}' token.
2440
Bill Wendling50d0f582010-11-18 23:43:05 +00002441 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2442 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002443}
2444
Jim Grosbach862019c2011-10-18 23:02:30 +00002445// parse a vector register list
2446ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2447parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2448 if(Parser.getTok().isNot(AsmToken::LCurly))
2449 return MatchOperand_NoMatch;
2450
2451 SMLoc S = Parser.getTok().getLoc();
2452 Parser.Lex(); // Eat '{' token.
2453 SMLoc RegLoc = Parser.getTok().getLoc();
2454
2455 int Reg = tryParseRegister();
2456 if (Reg == -1) {
2457 Error(RegLoc, "register expected");
2458 return MatchOperand_ParseFail;
2459 }
2460
2461 unsigned FirstReg = Reg;
2462 unsigned Count = 1;
2463 while (Parser.getTok().is(AsmToken::Comma)) {
2464 Parser.Lex(); // Eat the comma.
2465 RegLoc = Parser.getTok().getLoc();
2466 int OldReg = Reg;
2467 Reg = tryParseRegister();
2468 if (Reg == -1) {
2469 Error(RegLoc, "register expected");
2470 return MatchOperand_ParseFail;
2471 }
2472 // vector register lists must also be contiguous.
2473 // It's OK to use the enumeration values directly here rather, as the
2474 // VFP register classes have the enum sorted properly.
2475 if (Reg != OldReg + 1) {
2476 Error(RegLoc, "non-contiguous register range");
2477 return MatchOperand_ParseFail;
2478 }
2479
2480 ++Count;
2481 }
2482
2483 SMLoc E = Parser.getTok().getLoc();
2484 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2485 Error(E, "'}' expected");
2486 return MatchOperand_ParseFail;
2487 }
2488 Parser.Lex(); // Eat '}' token.
2489
2490 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2491 return MatchOperand_Success;
2492}
2493
Jim Grosbach43904292011-07-25 20:14:50 +00002494/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002495ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002496parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002497 SMLoc S = Parser.getTok().getLoc();
2498 const AsmToken &Tok = Parser.getTok();
2499 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2500 StringRef OptStr = Tok.getString();
2501
2502 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2503 .Case("sy", ARM_MB::SY)
2504 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002505 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002506 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002507 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002508 .Case("ishst", ARM_MB::ISHST)
2509 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002510 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002511 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002512 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002513 .Case("osh", ARM_MB::OSH)
2514 .Case("oshst", ARM_MB::OSHST)
2515 .Default(~0U);
2516
2517 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002518 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002519
2520 Parser.Lex(); // Eat identifier token.
2521 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002522 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002523}
2524
Jim Grosbach43904292011-07-25 20:14:50 +00002525/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002526ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002527parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002528 SMLoc S = Parser.getTok().getLoc();
2529 const AsmToken &Tok = Parser.getTok();
2530 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2531 StringRef IFlagsStr = Tok.getString();
2532
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002533 // An iflags string of "none" is interpreted to mean that none of the AIF
2534 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002535 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002536 if (IFlagsStr != "none") {
2537 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2538 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2539 .Case("a", ARM_PROC::A)
2540 .Case("i", ARM_PROC::I)
2541 .Case("f", ARM_PROC::F)
2542 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002543
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002544 // If some specific iflag is already set, it means that some letter is
2545 // present more than once, this is not acceptable.
2546 if (Flag == ~0U || (IFlags & Flag))
2547 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002548
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002549 IFlags |= Flag;
2550 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002551 }
2552
2553 Parser.Lex(); // Eat identifier token.
2554 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2555 return MatchOperand_Success;
2556}
2557
Jim Grosbach43904292011-07-25 20:14:50 +00002558/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002559ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002560parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002561 SMLoc S = Parser.getTok().getLoc();
2562 const AsmToken &Tok = Parser.getTok();
2563 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2564 StringRef Mask = Tok.getString();
2565
James Molloyacad68d2011-09-28 14:21:38 +00002566 if (isMClass()) {
2567 // See ARMv6-M 10.1.1
2568 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2569 .Case("apsr", 0)
2570 .Case("iapsr", 1)
2571 .Case("eapsr", 2)
2572 .Case("xpsr", 3)
2573 .Case("ipsr", 5)
2574 .Case("epsr", 6)
2575 .Case("iepsr", 7)
2576 .Case("msp", 8)
2577 .Case("psp", 9)
2578 .Case("primask", 16)
2579 .Case("basepri", 17)
2580 .Case("basepri_max", 18)
2581 .Case("faultmask", 19)
2582 .Case("control", 20)
2583 .Default(~0U);
2584
2585 if (FlagsVal == ~0U)
2586 return MatchOperand_NoMatch;
2587
2588 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2589 // basepri, basepri_max and faultmask only valid for V7m.
2590 return MatchOperand_NoMatch;
2591
2592 Parser.Lex(); // Eat identifier token.
2593 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2594 return MatchOperand_Success;
2595 }
2596
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002597 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2598 size_t Start = 0, Next = Mask.find('_');
2599 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002600 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002601 if (Next != StringRef::npos)
2602 Flags = Mask.slice(Next+1, Mask.size());
2603
2604 // FlagsVal contains the complete mask:
2605 // 3-0: Mask
2606 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2607 unsigned FlagsVal = 0;
2608
2609 if (SpecReg == "apsr") {
2610 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002611 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002612 .Case("g", 0x4) // same as CPSR_s
2613 .Case("nzcvqg", 0xc) // same as CPSR_fs
2614 .Default(~0U);
2615
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002616 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002617 if (!Flags.empty())
2618 return MatchOperand_NoMatch;
2619 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002620 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002621 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002622 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002623 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2624 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002625 for (int i = 0, e = Flags.size(); i != e; ++i) {
2626 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2627 .Case("c", 1)
2628 .Case("x", 2)
2629 .Case("s", 4)
2630 .Case("f", 8)
2631 .Default(~0U);
2632
2633 // If some specific flag is already set, it means that some letter is
2634 // present more than once, this is not acceptable.
2635 if (FlagsVal == ~0U || (FlagsVal & Flag))
2636 return MatchOperand_NoMatch;
2637 FlagsVal |= Flag;
2638 }
2639 } else // No match for special register.
2640 return MatchOperand_NoMatch;
2641
Owen Anderson7784f1d2011-10-21 18:43:28 +00002642 // Special register without flags is NOT equivalent to "fc" flags.
2643 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2644 // two lines would enable gas compatibility at the expense of breaking
2645 // round-tripping.
2646 //
2647 // if (!FlagsVal)
2648 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002649
2650 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2651 if (SpecReg == "spsr")
2652 FlagsVal |= 16;
2653
2654 Parser.Lex(); // Eat identifier token.
2655 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2656 return MatchOperand_Success;
2657}
2658
Jim Grosbachf6c05252011-07-21 17:23:04 +00002659ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2660parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2661 int Low, int High) {
2662 const AsmToken &Tok = Parser.getTok();
2663 if (Tok.isNot(AsmToken::Identifier)) {
2664 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2665 return MatchOperand_ParseFail;
2666 }
2667 StringRef ShiftName = Tok.getString();
2668 std::string LowerOp = LowercaseString(Op);
2669 std::string UpperOp = UppercaseString(Op);
2670 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2671 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2672 return MatchOperand_ParseFail;
2673 }
2674 Parser.Lex(); // Eat shift type token.
2675
2676 // There must be a '#' and a shift amount.
2677 if (Parser.getTok().isNot(AsmToken::Hash)) {
2678 Error(Parser.getTok().getLoc(), "'#' expected");
2679 return MatchOperand_ParseFail;
2680 }
2681 Parser.Lex(); // Eat hash token.
2682
2683 const MCExpr *ShiftAmount;
2684 SMLoc Loc = Parser.getTok().getLoc();
2685 if (getParser().ParseExpression(ShiftAmount)) {
2686 Error(Loc, "illegal expression");
2687 return MatchOperand_ParseFail;
2688 }
2689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2690 if (!CE) {
2691 Error(Loc, "constant expression expected");
2692 return MatchOperand_ParseFail;
2693 }
2694 int Val = CE->getValue();
2695 if (Val < Low || Val > High) {
2696 Error(Loc, "immediate value out of range");
2697 return MatchOperand_ParseFail;
2698 }
2699
2700 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2701
2702 return MatchOperand_Success;
2703}
2704
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002705ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2706parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2707 const AsmToken &Tok = Parser.getTok();
2708 SMLoc S = Tok.getLoc();
2709 if (Tok.isNot(AsmToken::Identifier)) {
2710 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2711 return MatchOperand_ParseFail;
2712 }
2713 int Val = StringSwitch<int>(Tok.getString())
2714 .Case("be", 1)
2715 .Case("le", 0)
2716 .Default(-1);
2717 Parser.Lex(); // Eat the token.
2718
2719 if (Val == -1) {
2720 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2721 return MatchOperand_ParseFail;
2722 }
2723 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2724 getContext()),
2725 S, Parser.getTok().getLoc()));
2726 return MatchOperand_Success;
2727}
2728
Jim Grosbach580f4a92011-07-25 22:20:28 +00002729/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2730/// instructions. Legal values are:
2731/// lsl #n 'n' in [0,31]
2732/// asr #n 'n' in [1,32]
2733/// n == 32 encoded as n == 0.
2734ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2735parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2736 const AsmToken &Tok = Parser.getTok();
2737 SMLoc S = Tok.getLoc();
2738 if (Tok.isNot(AsmToken::Identifier)) {
2739 Error(S, "shift operator 'asr' or 'lsl' expected");
2740 return MatchOperand_ParseFail;
2741 }
2742 StringRef ShiftName = Tok.getString();
2743 bool isASR;
2744 if (ShiftName == "lsl" || ShiftName == "LSL")
2745 isASR = false;
2746 else if (ShiftName == "asr" || ShiftName == "ASR")
2747 isASR = true;
2748 else {
2749 Error(S, "shift operator 'asr' or 'lsl' expected");
2750 return MatchOperand_ParseFail;
2751 }
2752 Parser.Lex(); // Eat the operator.
2753
2754 // A '#' and a shift amount.
2755 if (Parser.getTok().isNot(AsmToken::Hash)) {
2756 Error(Parser.getTok().getLoc(), "'#' expected");
2757 return MatchOperand_ParseFail;
2758 }
2759 Parser.Lex(); // Eat hash token.
2760
2761 const MCExpr *ShiftAmount;
2762 SMLoc E = Parser.getTok().getLoc();
2763 if (getParser().ParseExpression(ShiftAmount)) {
2764 Error(E, "malformed shift expression");
2765 return MatchOperand_ParseFail;
2766 }
2767 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2768 if (!CE) {
2769 Error(E, "shift amount must be an immediate");
2770 return MatchOperand_ParseFail;
2771 }
2772
2773 int64_t Val = CE->getValue();
2774 if (isASR) {
2775 // Shift amount must be in [1,32]
2776 if (Val < 1 || Val > 32) {
2777 Error(E, "'asr' shift amount must be in range [1,32]");
2778 return MatchOperand_ParseFail;
2779 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002780 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2781 if (isThumb() && Val == 32) {
2782 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2783 return MatchOperand_ParseFail;
2784 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002785 if (Val == 32) Val = 0;
2786 } else {
2787 // Shift amount must be in [1,32]
2788 if (Val < 0 || Val > 31) {
2789 Error(E, "'lsr' shift amount must be in range [0,31]");
2790 return MatchOperand_ParseFail;
2791 }
2792 }
2793
2794 E = Parser.getTok().getLoc();
2795 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2796
2797 return MatchOperand_Success;
2798}
2799
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002800/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2801/// of instructions. Legal values are:
2802/// ror #n 'n' in {0, 8, 16, 24}
2803ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2804parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2805 const AsmToken &Tok = Parser.getTok();
2806 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002807 if (Tok.isNot(AsmToken::Identifier))
2808 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002809 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002810 if (ShiftName != "ror" && ShiftName != "ROR")
2811 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002812 Parser.Lex(); // Eat the operator.
2813
2814 // A '#' and a rotate amount.
2815 if (Parser.getTok().isNot(AsmToken::Hash)) {
2816 Error(Parser.getTok().getLoc(), "'#' expected");
2817 return MatchOperand_ParseFail;
2818 }
2819 Parser.Lex(); // Eat hash token.
2820
2821 const MCExpr *ShiftAmount;
2822 SMLoc E = Parser.getTok().getLoc();
2823 if (getParser().ParseExpression(ShiftAmount)) {
2824 Error(E, "malformed rotate expression");
2825 return MatchOperand_ParseFail;
2826 }
2827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2828 if (!CE) {
2829 Error(E, "rotate amount must be an immediate");
2830 return MatchOperand_ParseFail;
2831 }
2832
2833 int64_t Val = CE->getValue();
2834 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2835 // normally, zero is represented in asm by omitting the rotate operand
2836 // entirely.
2837 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2838 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2839 return MatchOperand_ParseFail;
2840 }
2841
2842 E = Parser.getTok().getLoc();
2843 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2844
2845 return MatchOperand_Success;
2846}
2847
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002848ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2849parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2850 SMLoc S = Parser.getTok().getLoc();
2851 // The bitfield descriptor is really two operands, the LSB and the width.
2852 if (Parser.getTok().isNot(AsmToken::Hash)) {
2853 Error(Parser.getTok().getLoc(), "'#' expected");
2854 return MatchOperand_ParseFail;
2855 }
2856 Parser.Lex(); // Eat hash token.
2857
2858 const MCExpr *LSBExpr;
2859 SMLoc E = Parser.getTok().getLoc();
2860 if (getParser().ParseExpression(LSBExpr)) {
2861 Error(E, "malformed immediate expression");
2862 return MatchOperand_ParseFail;
2863 }
2864 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2865 if (!CE) {
2866 Error(E, "'lsb' operand must be an immediate");
2867 return MatchOperand_ParseFail;
2868 }
2869
2870 int64_t LSB = CE->getValue();
2871 // The LSB must be in the range [0,31]
2872 if (LSB < 0 || LSB > 31) {
2873 Error(E, "'lsb' operand must be in the range [0,31]");
2874 return MatchOperand_ParseFail;
2875 }
2876 E = Parser.getTok().getLoc();
2877
2878 // Expect another immediate operand.
2879 if (Parser.getTok().isNot(AsmToken::Comma)) {
2880 Error(Parser.getTok().getLoc(), "too few operands");
2881 return MatchOperand_ParseFail;
2882 }
2883 Parser.Lex(); // Eat hash token.
2884 if (Parser.getTok().isNot(AsmToken::Hash)) {
2885 Error(Parser.getTok().getLoc(), "'#' expected");
2886 return MatchOperand_ParseFail;
2887 }
2888 Parser.Lex(); // Eat hash token.
2889
2890 const MCExpr *WidthExpr;
2891 if (getParser().ParseExpression(WidthExpr)) {
2892 Error(E, "malformed immediate expression");
2893 return MatchOperand_ParseFail;
2894 }
2895 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2896 if (!CE) {
2897 Error(E, "'width' operand must be an immediate");
2898 return MatchOperand_ParseFail;
2899 }
2900
2901 int64_t Width = CE->getValue();
2902 // The LSB must be in the range [1,32-lsb]
2903 if (Width < 1 || Width > 32 - LSB) {
2904 Error(E, "'width' operand must be in the range [1,32-lsb]");
2905 return MatchOperand_ParseFail;
2906 }
2907 E = Parser.getTok().getLoc();
2908
2909 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2910
2911 return MatchOperand_Success;
2912}
2913
Jim Grosbach7ce05792011-08-03 23:50:40 +00002914ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2915parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2916 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002917 // postidx_reg := '+' register {, shift}
2918 // | '-' register {, shift}
2919 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002920
2921 // This method must return MatchOperand_NoMatch without consuming any tokens
2922 // in the case where there is no match, as other alternatives take other
2923 // parse methods.
2924 AsmToken Tok = Parser.getTok();
2925 SMLoc S = Tok.getLoc();
2926 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002927 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002928 int Reg = -1;
2929 if (Tok.is(AsmToken::Plus)) {
2930 Parser.Lex(); // Eat the '+' token.
2931 haveEaten = true;
2932 } else if (Tok.is(AsmToken::Minus)) {
2933 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002934 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002935 haveEaten = true;
2936 }
2937 if (Parser.getTok().is(AsmToken::Identifier))
2938 Reg = tryParseRegister();
2939 if (Reg == -1) {
2940 if (!haveEaten)
2941 return MatchOperand_NoMatch;
2942 Error(Parser.getTok().getLoc(), "register expected");
2943 return MatchOperand_ParseFail;
2944 }
2945 SMLoc E = Parser.getTok().getLoc();
2946
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002947 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2948 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002949 if (Parser.getTok().is(AsmToken::Comma)) {
2950 Parser.Lex(); // Eat the ','.
2951 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2952 return MatchOperand_ParseFail;
2953 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002954
2955 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2956 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002957
2958 return MatchOperand_Success;
2959}
2960
Jim Grosbach251bf252011-08-10 21:56:18 +00002961ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2962parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2963 // Check for a post-index addressing register operand. Specifically:
2964 // am3offset := '+' register
2965 // | '-' register
2966 // | register
2967 // | # imm
2968 // | # + imm
2969 // | # - imm
2970
2971 // This method must return MatchOperand_NoMatch without consuming any tokens
2972 // in the case where there is no match, as other alternatives take other
2973 // parse methods.
2974 AsmToken Tok = Parser.getTok();
2975 SMLoc S = Tok.getLoc();
2976
2977 // Do immediates first, as we always parse those if we have a '#'.
2978 if (Parser.getTok().is(AsmToken::Hash)) {
2979 Parser.Lex(); // Eat the '#'.
2980 // Explicitly look for a '-', as we need to encode negative zero
2981 // differently.
2982 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2983 const MCExpr *Offset;
2984 if (getParser().ParseExpression(Offset))
2985 return MatchOperand_ParseFail;
2986 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2987 if (!CE) {
2988 Error(S, "constant expression expected");
2989 return MatchOperand_ParseFail;
2990 }
2991 SMLoc E = Tok.getLoc();
2992 // Negative zero is encoded as the flag value INT32_MIN.
2993 int32_t Val = CE->getValue();
2994 if (isNegative && Val == 0)
2995 Val = INT32_MIN;
2996
2997 Operands.push_back(
2998 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2999
3000 return MatchOperand_Success;
3001 }
3002
3003
3004 bool haveEaten = false;
3005 bool isAdd = true;
3006 int Reg = -1;
3007 if (Tok.is(AsmToken::Plus)) {
3008 Parser.Lex(); // Eat the '+' token.
3009 haveEaten = true;
3010 } else if (Tok.is(AsmToken::Minus)) {
3011 Parser.Lex(); // Eat the '-' token.
3012 isAdd = false;
3013 haveEaten = true;
3014 }
3015 if (Parser.getTok().is(AsmToken::Identifier))
3016 Reg = tryParseRegister();
3017 if (Reg == -1) {
3018 if (!haveEaten)
3019 return MatchOperand_NoMatch;
3020 Error(Parser.getTok().getLoc(), "register expected");
3021 return MatchOperand_ParseFail;
3022 }
3023 SMLoc E = Parser.getTok().getLoc();
3024
3025 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3026 0, S, E));
3027
3028 return MatchOperand_Success;
3029}
3030
Jim Grosbacha77295d2011-09-08 22:07:06 +00003031/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3032/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3033/// when they refer multiple MIOperands inside a single one.
3034bool ARMAsmParser::
3035cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3036 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3037 // Rt, Rt2
3038 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3039 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3040 // Create a writeback register dummy placeholder.
3041 Inst.addOperand(MCOperand::CreateReg(0));
3042 // addr
3043 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3044 // pred
3045 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3046 return true;
3047}
3048
3049/// cvtT2StrdPre - Convert parsed operands to MCInst.
3050/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3051/// when they refer multiple MIOperands inside a single one.
3052bool ARMAsmParser::
3053cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3054 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3055 // Create a writeback register dummy placeholder.
3056 Inst.addOperand(MCOperand::CreateReg(0));
3057 // Rt, Rt2
3058 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3059 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3060 // addr
3061 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3062 // pred
3063 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3064 return true;
3065}
3066
Jim Grosbacheeec0252011-09-08 00:39:19 +00003067/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3068/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3069/// when they refer multiple MIOperands inside a single one.
3070bool ARMAsmParser::
3071cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3072 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3073 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3074
3075 // Create a writeback register dummy placeholder.
3076 Inst.addOperand(MCOperand::CreateImm(0));
3077
3078 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3079 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3080 return true;
3081}
3082
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003083/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3084/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3085/// when they refer multiple MIOperands inside a single one.
3086bool ARMAsmParser::
3087cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3088 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3089 // Create a writeback register dummy placeholder.
3090 Inst.addOperand(MCOperand::CreateImm(0));
3091 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3092 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3093 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3094 return true;
3095}
3096
Jim Grosbach1355cf12011-07-26 17:10:22 +00003097/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003098/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3099/// when they refer multiple MIOperands inside a single one.
3100bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003101cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003102 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3103 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3104
3105 // Create a writeback register dummy placeholder.
3106 Inst.addOperand(MCOperand::CreateImm(0));
3107
Jim Grosbach7ce05792011-08-03 23:50:40 +00003108 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003109 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3110 return true;
3111}
3112
Owen Anderson9ab0f252011-08-26 20:43:14 +00003113/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3114/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3115/// when they refer multiple MIOperands inside a single one.
3116bool ARMAsmParser::
3117cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3118 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3119 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3120
3121 // Create a writeback register dummy placeholder.
3122 Inst.addOperand(MCOperand::CreateImm(0));
3123
3124 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3125 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3126 return true;
3127}
3128
3129
Jim Grosbach548340c2011-08-11 19:22:40 +00003130/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3131/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3132/// when they refer multiple MIOperands inside a single one.
3133bool ARMAsmParser::
3134cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3135 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3136 // Create a writeback register dummy placeholder.
3137 Inst.addOperand(MCOperand::CreateImm(0));
3138 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3139 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3140 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3141 return true;
3142}
3143
Jim Grosbach1355cf12011-07-26 17:10:22 +00003144/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003145/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3146/// when they refer multiple MIOperands inside a single one.
3147bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003148cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003149 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3150 // Create a writeback register dummy placeholder.
3151 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003152 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3153 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3154 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003155 return true;
3156}
3157
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003158/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3159/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3160/// when they refer multiple MIOperands inside a single one.
3161bool ARMAsmParser::
3162cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3163 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3164 // Create a writeback register dummy placeholder.
3165 Inst.addOperand(MCOperand::CreateImm(0));
3166 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3167 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3168 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3169 return true;
3170}
3171
Jim Grosbach7ce05792011-08-03 23:50:40 +00003172/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3173/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3174/// when they refer multiple MIOperands inside a single one.
3175bool ARMAsmParser::
3176cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3177 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3178 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003179 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003180 // Create a writeback register dummy placeholder.
3181 Inst.addOperand(MCOperand::CreateImm(0));
3182 // addr
3183 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3184 // offset
3185 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3186 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003187 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3188 return true;
3189}
3190
Jim Grosbach7ce05792011-08-03 23:50:40 +00003191/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003192/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3193/// when they refer multiple MIOperands inside a single one.
3194bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003195cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3196 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3197 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003198 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003199 // Create a writeback register dummy placeholder.
3200 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003201 // addr
3202 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3203 // offset
3204 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3205 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003206 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3207 return true;
3208}
3209
Jim Grosbach7ce05792011-08-03 23:50:40 +00003210/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003211/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3212/// when they refer multiple MIOperands inside a single one.
3213bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003214cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3215 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003216 // Create a writeback register dummy placeholder.
3217 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003218 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003219 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003220 // addr
3221 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3222 // offset
3223 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3224 // pred
3225 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3226 return true;
3227}
3228
3229/// cvtStExtTWriteBackReg - 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::
3233cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3234 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3235 // Create a writeback register dummy placeholder.
3236 Inst.addOperand(MCOperand::CreateImm(0));
3237 // Rt
3238 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3239 // addr
3240 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3241 // offset
3242 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3243 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003244 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3245 return true;
3246}
3247
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003248/// cvtLdrdPre - Convert parsed operands to MCInst.
3249/// 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::
3252cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3253 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3254 // Rt, Rt2
3255 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3256 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3257 // Create a writeback register dummy placeholder.
3258 Inst.addOperand(MCOperand::CreateImm(0));
3259 // addr
3260 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3261 // pred
3262 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3263 return true;
3264}
3265
Jim Grosbach14605d12011-08-11 20:28:23 +00003266/// cvtStrdPre - Convert parsed operands to MCInst.
3267/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3268/// when they refer multiple MIOperands inside a single one.
3269bool ARMAsmParser::
3270cvtStrdPre(MCInst &Inst, unsigned Opcode,
3271 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3272 // Create a writeback register dummy placeholder.
3273 Inst.addOperand(MCOperand::CreateImm(0));
3274 // Rt, Rt2
3275 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3276 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3277 // addr
3278 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3279 // pred
3280 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3281 return true;
3282}
3283
Jim Grosbach623a4542011-08-10 22:42:16 +00003284/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3285/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3286/// when they refer multiple MIOperands inside a single one.
3287bool ARMAsmParser::
3288cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3289 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3290 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3291 // Create a writeback register dummy placeholder.
3292 Inst.addOperand(MCOperand::CreateImm(0));
3293 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3294 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3295 return true;
3296}
3297
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003298/// cvtThumbMultiple- Convert parsed operands to MCInst.
3299/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3300/// when they refer multiple MIOperands inside a single one.
3301bool ARMAsmParser::
3302cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3303 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3304 // The second source operand must be the same register as the destination
3305 // operand.
3306 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003307 (((ARMOperand*)Operands[3])->getReg() !=
3308 ((ARMOperand*)Operands[5])->getReg()) &&
3309 (((ARMOperand*)Operands[3])->getReg() !=
3310 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003311 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003312 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003313 return false;
3314 }
3315 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3316 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3317 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003318 // If we have a three-operand form, use that, else the second source operand
3319 // is just the destination operand again.
3320 if (Operands.size() == 6)
3321 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3322 else
3323 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003324 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3325
3326 return true;
3327}
Jim Grosbach623a4542011-08-10 22:42:16 +00003328
Bill Wendlinge7176102010-11-06 22:36:58 +00003329/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003330/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003331bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003332parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003333 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003334 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003335 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003336 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003337 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003338
Sean Callanan18b83232010-01-19 21:44:56 +00003339 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003340 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003341 if (BaseRegNum == -1)
3342 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003343
Daniel Dunbar05710932011-01-18 05:34:17 +00003344 // The next token must either be a comma or a closing bracket.
3345 const AsmToken &Tok = Parser.getTok();
3346 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003347 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003348
Jim Grosbach7ce05792011-08-03 23:50:40 +00003349 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003350 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003351 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003352
Jim Grosbach7ce05792011-08-03 23:50:40 +00003353 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003354 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003355
Jim Grosbachfb12f352011-09-19 18:42:21 +00003356 // If there's a pre-indexing writeback marker, '!', just add it as a token
3357 // operand. It's rather odd, but syntactically valid.
3358 if (Parser.getTok().is(AsmToken::Exclaim)) {
3359 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3360 Parser.Lex(); // Eat the '!'.
3361 }
3362
Jim Grosbach7ce05792011-08-03 23:50:40 +00003363 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003364 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003365
Jim Grosbach7ce05792011-08-03 23:50:40 +00003366 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3367 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003368
Jim Grosbach57dcb852011-10-11 17:29:55 +00003369 // If we have a ':', it's an alignment specifier.
3370 if (Parser.getTok().is(AsmToken::Colon)) {
3371 Parser.Lex(); // Eat the ':'.
3372 E = Parser.getTok().getLoc();
3373
3374 const MCExpr *Expr;
3375 if (getParser().ParseExpression(Expr))
3376 return true;
3377
3378 // The expression has to be a constant. Memory references with relocations
3379 // don't come through here, as they use the <label> forms of the relevant
3380 // instructions.
3381 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3382 if (!CE)
3383 return Error (E, "constant expression expected");
3384
3385 unsigned Align = 0;
3386 switch (CE->getValue()) {
3387 default:
3388 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3389 case 64: Align = 8; break;
3390 case 128: Align = 16; break;
3391 case 256: Align = 32; break;
3392 }
3393
3394 // Now we should have the closing ']'
3395 E = Parser.getTok().getLoc();
3396 if (Parser.getTok().isNot(AsmToken::RBrac))
3397 return Error(E, "']' expected");
3398 Parser.Lex(); // Eat right bracket token.
3399
3400 // Don't worry about range checking the value here. That's handled by
3401 // the is*() predicates.
3402 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3403 ARM_AM::no_shift, 0, Align,
3404 false, S, E));
3405
3406 // If there's a pre-indexing writeback marker, '!', just add it as a token
3407 // operand.
3408 if (Parser.getTok().is(AsmToken::Exclaim)) {
3409 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3410 Parser.Lex(); // Eat the '!'.
3411 }
3412
3413 return false;
3414 }
3415
3416 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003417 // offset.
3418 if (Parser.getTok().is(AsmToken::Hash)) {
3419 Parser.Lex(); // Eat the '#'.
3420 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003421
Owen Anderson0da10cf2011-08-29 19:36:44 +00003422 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003423 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003424 if (getParser().ParseExpression(Offset))
3425 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003426
3427 // The expression has to be a constant. Memory references with relocations
3428 // don't come through here, as they use the <label> forms of the relevant
3429 // instructions.
3430 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3431 if (!CE)
3432 return Error (E, "constant expression expected");
3433
Owen Anderson0da10cf2011-08-29 19:36:44 +00003434 // If the constant was #-0, represent it as INT32_MIN.
3435 int32_t Val = CE->getValue();
3436 if (isNegative && Val == 0)
3437 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3438
Jim Grosbach7ce05792011-08-03 23:50:40 +00003439 // Now we should have the closing ']'
3440 E = Parser.getTok().getLoc();
3441 if (Parser.getTok().isNot(AsmToken::RBrac))
3442 return Error(E, "']' expected");
3443 Parser.Lex(); // Eat right bracket token.
3444
3445 // Don't worry about range checking the value here. That's handled by
3446 // the is*() predicates.
3447 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003448 ARM_AM::no_shift, 0, 0,
3449 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003450
3451 // If there's a pre-indexing writeback marker, '!', just add it as a token
3452 // operand.
3453 if (Parser.getTok().is(AsmToken::Exclaim)) {
3454 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3455 Parser.Lex(); // Eat the '!'.
3456 }
3457
3458 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003459 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003460
3461 // The register offset is optionally preceded by a '+' or '-'
3462 bool isNegative = false;
3463 if (Parser.getTok().is(AsmToken::Minus)) {
3464 isNegative = true;
3465 Parser.Lex(); // Eat the '-'.
3466 } else if (Parser.getTok().is(AsmToken::Plus)) {
3467 // Nothing to do.
3468 Parser.Lex(); // Eat the '+'.
3469 }
3470
3471 E = Parser.getTok().getLoc();
3472 int OffsetRegNum = tryParseRegister();
3473 if (OffsetRegNum == -1)
3474 return Error(E, "register expected");
3475
3476 // If there's a shift operator, handle it.
3477 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003478 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003479 if (Parser.getTok().is(AsmToken::Comma)) {
3480 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003481 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003482 return true;
3483 }
3484
3485 // Now we should have the closing ']'
3486 E = Parser.getTok().getLoc();
3487 if (Parser.getTok().isNot(AsmToken::RBrac))
3488 return Error(E, "']' expected");
3489 Parser.Lex(); // Eat right bracket token.
3490
3491 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003492 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003493 S, E));
3494
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003495 // If there's a pre-indexing writeback marker, '!', just add it as a token
3496 // operand.
3497 if (Parser.getTok().is(AsmToken::Exclaim)) {
3498 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3499 Parser.Lex(); // Eat the '!'.
3500 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003501
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003502 return false;
3503}
3504
Jim Grosbach7ce05792011-08-03 23:50:40 +00003505/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003506/// ( lsl | lsr | asr | ror ) , # shift_amount
3507/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003508/// return true if it parses a shift otherwise it returns false.
3509bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3510 unsigned &Amount) {
3511 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003512 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003513 if (Tok.isNot(AsmToken::Identifier))
3514 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003515 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003516 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003517 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003518 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003519 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003520 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003521 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003522 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003523 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003524 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003525 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003526 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003527 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003528 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003529
Jim Grosbach7ce05792011-08-03 23:50:40 +00003530 // rrx stands alone.
3531 Amount = 0;
3532 if (St != ARM_AM::rrx) {
3533 Loc = Parser.getTok().getLoc();
3534 // A '#' and a shift amount.
3535 const AsmToken &HashTok = Parser.getTok();
3536 if (HashTok.isNot(AsmToken::Hash))
3537 return Error(HashTok.getLoc(), "'#' expected");
3538 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003539
Jim Grosbach7ce05792011-08-03 23:50:40 +00003540 const MCExpr *Expr;
3541 if (getParser().ParseExpression(Expr))
3542 return true;
3543 // Range check the immediate.
3544 // lsl, ror: 0 <= imm <= 31
3545 // lsr, asr: 0 <= imm <= 32
3546 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3547 if (!CE)
3548 return Error(Loc, "shift amount must be an immediate");
3549 int64_t Imm = CE->getValue();
3550 if (Imm < 0 ||
3551 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3552 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3553 return Error(Loc, "immediate shift value out of range");
3554 Amount = Imm;
3555 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003556
3557 return false;
3558}
3559
Jim Grosbach9d390362011-10-03 23:38:36 +00003560/// parseFPImm - A floating point immediate expression operand.
3561ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3562parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3563 SMLoc S = Parser.getTok().getLoc();
3564
3565 if (Parser.getTok().isNot(AsmToken::Hash))
3566 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003567
3568 // Disambiguate the VMOV forms that can accept an FP immediate.
3569 // vmov.f32 <sreg>, #imm
3570 // vmov.f64 <dreg>, #imm
3571 // vmov.f32 <dreg>, #imm @ vector f32x2
3572 // vmov.f32 <qreg>, #imm @ vector f32x4
3573 //
3574 // There are also the NEON VMOV instructions which expect an
3575 // integer constant. Make sure we don't try to parse an FPImm
3576 // for these:
3577 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3578 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3579 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3580 TyOp->getToken() != ".f64"))
3581 return MatchOperand_NoMatch;
3582
Jim Grosbach9d390362011-10-03 23:38:36 +00003583 Parser.Lex(); // Eat the '#'.
3584
3585 // Handle negation, as that still comes through as a separate token.
3586 bool isNegative = false;
3587 if (Parser.getTok().is(AsmToken::Minus)) {
3588 isNegative = true;
3589 Parser.Lex();
3590 }
3591 const AsmToken &Tok = Parser.getTok();
3592 if (Tok.is(AsmToken::Real)) {
3593 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3594 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3595 // If we had a '-' in front, toggle the sign bit.
3596 IntVal ^= (uint64_t)isNegative << 63;
3597 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3598 Parser.Lex(); // Eat the token.
3599 if (Val == -1) {
3600 TokError("floating point value out of range");
3601 return MatchOperand_ParseFail;
3602 }
3603 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3604 return MatchOperand_Success;
3605 }
3606 if (Tok.is(AsmToken::Integer)) {
3607 int64_t Val = Tok.getIntVal();
3608 Parser.Lex(); // Eat the token.
3609 if (Val > 255 || Val < 0) {
3610 TokError("encoded floating point value out of range");
3611 return MatchOperand_ParseFail;
3612 }
3613 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3614 return MatchOperand_Success;
3615 }
3616
3617 TokError("invalid floating point immediate");
3618 return MatchOperand_ParseFail;
3619}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003620/// Parse a arm instruction operand. For now this parses the operand regardless
3621/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003622bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003623 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003624 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003625
3626 // Check if the current operand has a custom associated parser, if so, try to
3627 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003628 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3629 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003630 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003631 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3632 // there was a match, but an error occurred, in which case, just return that
3633 // the operand parsing failed.
3634 if (ResTy == MatchOperand_ParseFail)
3635 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003636
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003637 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003638 default:
3639 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003640 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003641 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003642 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003643 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003644 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003645 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003646 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003647 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003648 else if (Res == -1) // irrecoverable error
3649 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003650 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3651 S = Parser.getTok().getLoc();
3652 Parser.Lex();
3653 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3654 return false;
3655 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003656
3657 // Fall though for the Identifier case that is not a register or a
3658 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003659 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003660 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3661 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003662 // This was not a register so parse other operands that start with an
3663 // identifier (like labels) as expressions and create them as immediates.
3664 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003665 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003666 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003667 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003668 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003669 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3670 return false;
3671 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003672 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003673 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003674 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003675 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003676 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003677 // #42 -> immediate.
3678 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003679 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003680 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003681 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003682 const MCExpr *ImmVal;
3683 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003684 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003685 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3686 if (!CE) {
3687 Error(S, "constant expression expected");
3688 return MatchOperand_ParseFail;
3689 }
3690 int32_t Val = CE->getValue();
3691 if (isNegative && Val == 0)
3692 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003693 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003694 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3695 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003696 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003697 case AsmToken::Colon: {
3698 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003699 // FIXME: Check it's an expression prefix,
3700 // e.g. (FOO - :lower16:BAR) isn't legal.
3701 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003702 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003703 return true;
3704
Evan Cheng75972122011-01-13 07:58:56 +00003705 const MCExpr *SubExprVal;
3706 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003707 return true;
3708
Evan Cheng75972122011-01-13 07:58:56 +00003709 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3710 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003711 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003712 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003713 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003714 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003715 }
3716}
3717
Jim Grosbach1355cf12011-07-26 17:10:22 +00003718// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003719// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003720bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003721 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003722
3723 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003724 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003725 Parser.Lex(); // Eat ':'
3726
3727 if (getLexer().isNot(AsmToken::Identifier)) {
3728 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3729 return true;
3730 }
3731
3732 StringRef IDVal = Parser.getTok().getIdentifier();
3733 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003734 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003735 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003736 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003737 } else {
3738 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3739 return true;
3740 }
3741 Parser.Lex();
3742
3743 if (getLexer().isNot(AsmToken::Colon)) {
3744 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3745 return true;
3746 }
3747 Parser.Lex(); // Eat the last ':'
3748 return false;
3749}
3750
Daniel Dunbar352e1482011-01-11 15:59:50 +00003751/// \brief Given a mnemonic, split out possible predication code and carry
3752/// setting letters to form a canonical mnemonic and flags.
3753//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003754// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003755// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003756StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003757 unsigned &PredicationCode,
3758 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003759 unsigned &ProcessorIMod,
3760 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003761 PredicationCode = ARMCC::AL;
3762 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003763 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003764
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003765 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003766 //
3767 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003768 if ((Mnemonic == "movs" && isThumb()) ||
3769 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3770 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3771 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3772 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3773 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3774 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3775 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003776 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003777
Jim Grosbach3f00e312011-07-11 17:09:57 +00003778 // First, split out any predication code. Ignore mnemonics we know aren't
3779 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003780 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003781 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003782 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003783 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003784 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3785 .Case("eq", ARMCC::EQ)
3786 .Case("ne", ARMCC::NE)
3787 .Case("hs", ARMCC::HS)
3788 .Case("cs", ARMCC::HS)
3789 .Case("lo", ARMCC::LO)
3790 .Case("cc", ARMCC::LO)
3791 .Case("mi", ARMCC::MI)
3792 .Case("pl", ARMCC::PL)
3793 .Case("vs", ARMCC::VS)
3794 .Case("vc", ARMCC::VC)
3795 .Case("hi", ARMCC::HI)
3796 .Case("ls", ARMCC::LS)
3797 .Case("ge", ARMCC::GE)
3798 .Case("lt", ARMCC::LT)
3799 .Case("gt", ARMCC::GT)
3800 .Case("le", ARMCC::LE)
3801 .Case("al", ARMCC::AL)
3802 .Default(~0U);
3803 if (CC != ~0U) {
3804 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3805 PredicationCode = CC;
3806 }
Bill Wendling52925b62010-10-29 23:50:21 +00003807 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003808
Daniel Dunbar352e1482011-01-11 15:59:50 +00003809 // Next, determine if we have a carry setting bit. We explicitly ignore all
3810 // the instructions we know end in 's'.
3811 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003812 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003813 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3814 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3815 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003816 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3817 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003818 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3819 CarrySetting = true;
3820 }
3821
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003822 // The "cps" instruction can have a interrupt mode operand which is glued into
3823 // the mnemonic. Check if this is the case, split it and parse the imod op
3824 if (Mnemonic.startswith("cps")) {
3825 // Split out any imod code.
3826 unsigned IMod =
3827 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3828 .Case("ie", ARM_PROC::IE)
3829 .Case("id", ARM_PROC::ID)
3830 .Default(~0U);
3831 if (IMod != ~0U) {
3832 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3833 ProcessorIMod = IMod;
3834 }
3835 }
3836
Jim Grosbach89df9962011-08-26 21:43:41 +00003837 // The "it" instruction has the condition mask on the end of the mnemonic.
3838 if (Mnemonic.startswith("it")) {
3839 ITMask = Mnemonic.slice(2, Mnemonic.size());
3840 Mnemonic = Mnemonic.slice(0, 2);
3841 }
3842
Daniel Dunbar352e1482011-01-11 15:59:50 +00003843 return Mnemonic;
3844}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003845
3846/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3847/// inclusion of carry set or predication code operands.
3848//
3849// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003850void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003851getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003852 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003853 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3854 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003855 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003856 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003857 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003858 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003859 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003860 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003861 Mnemonic == "mla" || Mnemonic == "smlal" ||
3862 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003863 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003864 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003865 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003866
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003867 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3868 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3869 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3870 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003871 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3872 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003873 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003874 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3875 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3876 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003877 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3878 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003879 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003880 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003881 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003882 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003883
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003884 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003885 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003886 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003887 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003888 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003889}
3890
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003891bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3892 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003893 // FIXME: This is all horribly hacky. We really need a better way to deal
3894 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003895
3896 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3897 // another does not. Specifically, the MOVW instruction does not. So we
3898 // special case it here and remove the defaulted (non-setting) cc_out
3899 // operand if that's the instruction we're trying to match.
3900 //
3901 // We do this as post-processing of the explicit operands rather than just
3902 // conditionally adding the cc_out in the first place because we need
3903 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003904 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003905 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3906 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3907 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3908 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003909
3910 // Register-register 'add' for thumb does not have a cc_out operand
3911 // when there are only two register operands.
3912 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3913 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3914 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3915 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3916 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003917 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003918 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3919 // have to check the immediate range here since Thumb2 has a variant
3920 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003921 if (((isThumb() && Mnemonic == "add") ||
3922 (isThumbTwo() && Mnemonic == "sub")) &&
3923 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003924 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3925 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3926 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003927 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3928 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3929 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003930 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003931 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3932 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003933 // selecting via the generic "add" mnemonic, so to know that we
3934 // should remove the cc_out operand, we have to explicitly check that
3935 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003936 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3937 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003938 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3939 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3940 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3941 // Nest conditions rather than one big 'if' statement for readability.
3942 //
3943 // If either register is a high reg, it's either one of the SP
3944 // variants (handled above) or a 32-bit encoding, so we just
3945 // check against T3.
3946 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3947 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3948 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3949 return false;
3950 // If both registers are low, we're in an IT block, and the immediate is
3951 // in range, we should use encoding T1 instead, which has a cc_out.
3952 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003953 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003954 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3955 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3956 return false;
3957
3958 // Otherwise, we use encoding T4, which does not have a cc_out
3959 // operand.
3960 return true;
3961 }
3962
Jim Grosbach64944f42011-09-14 21:00:40 +00003963 // The thumb2 multiply instruction doesn't have a CCOut register, so
3964 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3965 // use the 16-bit encoding or not.
3966 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3967 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3968 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3969 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3970 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3971 // If the registers aren't low regs, the destination reg isn't the
3972 // same as one of the source regs, or the cc_out operand is zero
3973 // outside of an IT block, we have to use the 32-bit encoding, so
3974 // remove the cc_out operand.
3975 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3976 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3977 !inITBlock() ||
3978 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3979 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3980 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3981 static_cast<ARMOperand*>(Operands[4])->getReg())))
3982 return true;
3983
3984
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003985
Jim Grosbachf69c8042011-08-24 21:42:27 +00003986 // Register-register 'add/sub' for thumb does not have a cc_out operand
3987 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3988 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3989 // right, this will result in better diagnostics (which operand is off)
3990 // anyway.
3991 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3992 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003993 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3994 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3995 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3996 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003997
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003998 return false;
3999}
4000
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004001/// Parse an arm instruction mnemonic followed by its operands.
4002bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4003 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4004 // Create the leading tokens for the mnemonic, split by '.' characters.
4005 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004006 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004007
Daniel Dunbar352e1482011-01-11 15:59:50 +00004008 // Split out the predication code and carry setting flag from the mnemonic.
4009 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004010 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004011 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004012 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004013 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004014 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004015
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004016 // In Thumb1, only the branch (B) instruction can be predicated.
4017 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4018 Parser.EatToEndOfStatement();
4019 return Error(NameLoc, "conditional execution not supported in Thumb1");
4020 }
4021
Jim Grosbachffa32252011-07-19 19:13:28 +00004022 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4023
Jim Grosbach89df9962011-08-26 21:43:41 +00004024 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4025 // is the mask as it will be for the IT encoding if the conditional
4026 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4027 // where the conditional bit0 is zero, the instruction post-processing
4028 // will adjust the mask accordingly.
4029 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004030 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4031 if (ITMask.size() > 3) {
4032 Parser.EatToEndOfStatement();
4033 return Error(Loc, "too many conditions on IT instruction");
4034 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004035 unsigned Mask = 8;
4036 for (unsigned i = ITMask.size(); i != 0; --i) {
4037 char pos = ITMask[i - 1];
4038 if (pos != 't' && pos != 'e') {
4039 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004040 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004041 }
4042 Mask >>= 1;
4043 if (ITMask[i - 1] == 't')
4044 Mask |= 8;
4045 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004046 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004047 }
4048
Jim Grosbachffa32252011-07-19 19:13:28 +00004049 // FIXME: This is all a pretty gross hack. We should automatically handle
4050 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004051
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004052 // Next, add the CCOut and ConditionCode operands, if needed.
4053 //
4054 // For mnemonics which can ever incorporate a carry setting bit or predication
4055 // code, our matching model involves us always generating CCOut and
4056 // ConditionCode operands to match the mnemonic "as written" and then we let
4057 // the matcher deal with finding the right instruction or generating an
4058 // appropriate error.
4059 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004060 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004061
Jim Grosbach33c16a22011-07-14 22:04:21 +00004062 // If we had a carry-set on an instruction that can't do that, issue an
4063 // error.
4064 if (!CanAcceptCarrySet && CarrySetting) {
4065 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004066 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004067 "' can not set flags, but 's' suffix specified");
4068 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004069 // If we had a predication code on an instruction that can't do that, issue an
4070 // error.
4071 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4072 Parser.EatToEndOfStatement();
4073 return Error(NameLoc, "instruction '" + Mnemonic +
4074 "' is not predicable, but condition code specified");
4075 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004076
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004077 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004078 if (CanAcceptCarrySet) {
4079 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004080 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004081 Loc));
4082 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004083
4084 // Add the predication code operand, if necessary.
4085 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004086 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4087 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004088 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004089 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004090 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004091
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004092 // Add the processor imod operand, if necessary.
4093 if (ProcessorIMod) {
4094 Operands.push_back(ARMOperand::CreateImm(
4095 MCConstantExpr::Create(ProcessorIMod, getContext()),
4096 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004097 }
4098
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004099 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004100 while (Next != StringRef::npos) {
4101 Start = Next;
4102 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004103 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004104
Jim Grosbach4d23e992011-08-24 22:19:48 +00004105 // For now, we're only parsing Thumb1 (for the most part), so
4106 // just ignore ".n" qualifiers. We'll use them to restrict
4107 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00004108 if (ExtraToken != ".n") {
4109 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4110 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4111 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004112 }
4113
4114 // Read the remaining operands.
4115 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004116 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004117 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004118 Parser.EatToEndOfStatement();
4119 return true;
4120 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004121
4122 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004123 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004124
4125 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004126 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004127 Parser.EatToEndOfStatement();
4128 return true;
4129 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004130 }
4131 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004132
Chris Lattnercbf8a982010-09-11 16:18:25 +00004133 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004134 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004135 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004136 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004137 }
Bill Wendling146018f2010-11-06 21:42:12 +00004138
Chris Lattner34e53142010-09-08 05:10:46 +00004139 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004140
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004141 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4142 // do and don't have a cc_out optional-def operand. With some spot-checks
4143 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004144 // parse and adjust accordingly before actually matching. We shouldn't ever
4145 // try to remove a cc_out operand that was explicitly set on the the
4146 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4147 // table driven matcher doesn't fit well with the ARM instruction set.
4148 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004149 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4150 Operands.erase(Operands.begin() + 1);
4151 delete Op;
4152 }
4153
Jim Grosbachcf121c32011-07-28 21:57:55 +00004154 // ARM mode 'blx' need special handling, as the register operand version
4155 // is predicable, but the label operand version is not. So, we can't rely
4156 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004157 // a k_CondCode operand in the list. If we're trying to match the label
4158 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004159 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4160 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4161 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4162 Operands.erase(Operands.begin() + 1);
4163 delete Op;
4164 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004165
4166 // The vector-compare-to-zero instructions have a literal token "#0" at
4167 // the end that comes to here as an immediate operand. Convert it to a
4168 // token to play nicely with the matcher.
4169 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4170 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4171 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4172 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4173 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4174 if (CE && CE->getValue() == 0) {
4175 Operands.erase(Operands.begin() + 5);
4176 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4177 delete Op;
4178 }
4179 }
Jim Grosbach68259142011-10-03 22:30:24 +00004180 // VCMP{E} does the same thing, but with a different operand count.
4181 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4182 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4183 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4184 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4185 if (CE && CE->getValue() == 0) {
4186 Operands.erase(Operands.begin() + 4);
4187 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4188 delete Op;
4189 }
4190 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004191 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4192 // end. Convert it to a token here.
4193 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4194 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4195 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4196 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4197 if (CE && CE->getValue() == 0) {
4198 Operands.erase(Operands.begin() + 5);
4199 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4200 delete Op;
4201 }
4202 }
4203
Chris Lattner98986712010-01-14 22:21:20 +00004204 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004205}
4206
Jim Grosbach189610f2011-07-26 18:25:39 +00004207// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004208
4209// return 'true' if register list contains non-low GPR registers,
4210// 'false' otherwise. If Reg is in the register list or is HiReg, set
4211// 'containsReg' to true.
4212static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4213 unsigned HiReg, bool &containsReg) {
4214 containsReg = false;
4215 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4216 unsigned OpReg = Inst.getOperand(i).getReg();
4217 if (OpReg == Reg)
4218 containsReg = true;
4219 // Anything other than a low register isn't legal here.
4220 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4221 return true;
4222 }
4223 return false;
4224}
4225
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004226// Check if the specified regisgter is in the register list of the inst,
4227// starting at the indicated operand number.
4228static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4229 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4230 unsigned OpReg = Inst.getOperand(i).getReg();
4231 if (OpReg == Reg)
4232 return true;
4233 }
4234 return false;
4235}
4236
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004237// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4238// the ARMInsts array) instead. Getting that here requires awkward
4239// API changes, though. Better way?
4240namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004241extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004242}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004243static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004244 return ARMInsts[Opcode];
4245}
4246
Jim Grosbach189610f2011-07-26 18:25:39 +00004247// FIXME: We would really like to be able to tablegen'erate this.
4248bool ARMAsmParser::
4249validateInstruction(MCInst &Inst,
4250 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004251 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004252 SMLoc Loc = Operands[0]->getStartLoc();
4253 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004254 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4255 // being allowed in IT blocks, but not being predicable. It just always
4256 // executes.
4257 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004258 unsigned bit = 1;
4259 if (ITState.FirstCond)
4260 ITState.FirstCond = false;
4261 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004262 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004263 // The instruction must be predicable.
4264 if (!MCID.isPredicable())
4265 return Error(Loc, "instructions in IT block must be predicable");
4266 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4267 unsigned ITCond = bit ? ITState.Cond :
4268 ARMCC::getOppositeCondition(ITState.Cond);
4269 if (Cond != ITCond) {
4270 // Find the condition code Operand to get its SMLoc information.
4271 SMLoc CondLoc;
4272 for (unsigned i = 1; i < Operands.size(); ++i)
4273 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4274 CondLoc = Operands[i]->getStartLoc();
4275 return Error(CondLoc, "incorrect condition in IT block; got '" +
4276 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4277 "', but expected '" +
4278 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4279 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004280 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004281 } else if (isThumbTwo() && MCID.isPredicable() &&
4282 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004283 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4284 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004285 return Error(Loc, "predicated instructions must be in IT block");
4286
Jim Grosbach189610f2011-07-26 18:25:39 +00004287 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004288 case ARM::LDRD:
4289 case ARM::LDRD_PRE:
4290 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004291 case ARM::LDREXD: {
4292 // Rt2 must be Rt + 1.
4293 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4294 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4295 if (Rt2 != Rt + 1)
4296 return Error(Operands[3]->getStartLoc(),
4297 "destination operands must be sequential");
4298 return false;
4299 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004300 case ARM::STRD: {
4301 // Rt2 must be Rt + 1.
4302 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4303 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4304 if (Rt2 != Rt + 1)
4305 return Error(Operands[3]->getStartLoc(),
4306 "source operands must be sequential");
4307 return false;
4308 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004309 case ARM::STRD_PRE:
4310 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004311 case ARM::STREXD: {
4312 // Rt2 must be Rt + 1.
4313 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4314 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4315 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004316 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004317 "source operands must be sequential");
4318 return false;
4319 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004320 case ARM::SBFX:
4321 case ARM::UBFX: {
4322 // width must be in range [1, 32-lsb]
4323 unsigned lsb = Inst.getOperand(2).getImm();
4324 unsigned widthm1 = Inst.getOperand(3).getImm();
4325 if (widthm1 >= 32 - lsb)
4326 return Error(Operands[5]->getStartLoc(),
4327 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004328 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004329 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004330 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004331 // If we're parsing Thumb2, the .w variant is available and handles
4332 // most cases that are normally illegal for a Thumb1 LDM
4333 // instruction. We'll make the transformation in processInstruction()
4334 // if necessary.
4335 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004336 // Thumb LDM instructions are writeback iff the base register is not
4337 // in the register list.
4338 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004339 bool hasWritebackToken =
4340 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4341 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004342 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004343 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004344 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4345 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004346 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004347 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004348 return Error(Operands[2]->getStartLoc(),
4349 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004350 // If we should not have writeback, there must not be a '!'. This is
4351 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004352 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004353 return Error(Operands[3]->getStartLoc(),
4354 "writeback operator '!' not allowed when base register "
4355 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004356
4357 break;
4358 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004359 case ARM::t2LDMIA_UPD: {
4360 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4361 return Error(Operands[4]->getStartLoc(),
4362 "writeback operator '!' not allowed when base register "
4363 "in register list");
4364 break;
4365 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004366 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004367 bool listContainsBase;
4368 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4369 return Error(Operands[2]->getStartLoc(),
4370 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004371 break;
4372 }
4373 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004374 bool listContainsBase;
4375 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4376 return Error(Operands[2]->getStartLoc(),
4377 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004378 break;
4379 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004380 case ARM::tSTMIA_UPD: {
4381 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004382 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004383 return Error(Operands[4]->getStartLoc(),
4384 "registers must be in range r0-r7");
4385 break;
4386 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004387 }
4388
4389 return false;
4390}
4391
Jim Grosbachf8fce712011-08-11 17:35:48 +00004392void ARMAsmParser::
4393processInstruction(MCInst &Inst,
4394 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4395 switch (Inst.getOpcode()) {
4396 case ARM::LDMIA_UPD:
4397 // If this is a load of a single register via a 'pop', then we should use
4398 // a post-indexed LDR instruction instead, per the ARM ARM.
4399 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4400 Inst.getNumOperands() == 5) {
4401 MCInst TmpInst;
4402 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4403 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4404 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4405 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4406 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4407 TmpInst.addOperand(MCOperand::CreateImm(4));
4408 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4409 TmpInst.addOperand(Inst.getOperand(3));
4410 Inst = TmpInst;
4411 }
4412 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004413 case ARM::STMDB_UPD:
4414 // If this is a store of a single register via a 'push', then we should use
4415 // a pre-indexed STR instruction instead, per the ARM ARM.
4416 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4417 Inst.getNumOperands() == 5) {
4418 MCInst TmpInst;
4419 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4420 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4421 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4422 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4423 TmpInst.addOperand(MCOperand::CreateImm(-4));
4424 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4425 TmpInst.addOperand(Inst.getOperand(3));
4426 Inst = TmpInst;
4427 }
4428 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004429 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004430 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4431 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4432 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4433 // to encoding T1 if <Rd> is omitted."
4434 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004435 Inst.setOpcode(ARM::tADDi3);
4436 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004437 case ARM::tSUBi8:
4438 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4439 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4440 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4441 // to encoding T1 if <Rd> is omitted."
4442 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4443 Inst.setOpcode(ARM::tSUBi3);
4444 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004445 case ARM::tB:
4446 // A Thumb conditional branch outside of an IT block is a tBcc.
4447 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4448 Inst.setOpcode(ARM::tBcc);
4449 break;
4450 case ARM::t2B:
4451 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4452 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4453 Inst.setOpcode(ARM::t2Bcc);
4454 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004455 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004456 // If the conditional is AL or we're in an IT block, we really want t2B.
4457 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004458 Inst.setOpcode(ARM::t2B);
4459 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004460 case ARM::tBcc:
4461 // If the conditional is AL, we really want tB.
4462 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4463 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004464 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004465 case ARM::tLDMIA: {
4466 // If the register list contains any high registers, or if the writeback
4467 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4468 // instead if we're in Thumb2. Otherwise, this should have generated
4469 // an error in validateInstruction().
4470 unsigned Rn = Inst.getOperand(0).getReg();
4471 bool hasWritebackToken =
4472 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4473 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4474 bool listContainsBase;
4475 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4476 (!listContainsBase && !hasWritebackToken) ||
4477 (listContainsBase && hasWritebackToken)) {
4478 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4479 assert (isThumbTwo());
4480 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4481 // If we're switching to the updating version, we need to insert
4482 // the writeback tied operand.
4483 if (hasWritebackToken)
4484 Inst.insert(Inst.begin(),
4485 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4486 }
4487 break;
4488 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004489 case ARM::tSTMIA_UPD: {
4490 // If the register list contains any high registers, we need to use
4491 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4492 // should have generated an error in validateInstruction().
4493 unsigned Rn = Inst.getOperand(0).getReg();
4494 bool listContainsBase;
4495 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4496 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4497 assert (isThumbTwo());
4498 Inst.setOpcode(ARM::t2STMIA_UPD);
4499 }
4500 break;
4501 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004502 case ARM::t2MOVi: {
4503 // If we can use the 16-bit encoding and the user didn't explicitly
4504 // request the 32-bit variant, transform it here.
4505 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4506 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004507 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4508 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4509 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004510 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4511 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4512 // The operands aren't in the same order for tMOVi8...
4513 MCInst TmpInst;
4514 TmpInst.setOpcode(ARM::tMOVi8);
4515 TmpInst.addOperand(Inst.getOperand(0));
4516 TmpInst.addOperand(Inst.getOperand(4));
4517 TmpInst.addOperand(Inst.getOperand(1));
4518 TmpInst.addOperand(Inst.getOperand(2));
4519 TmpInst.addOperand(Inst.getOperand(3));
4520 Inst = TmpInst;
4521 }
4522 break;
4523 }
4524 case ARM::t2MOVr: {
4525 // If we can use the 16-bit encoding and the user didn't explicitly
4526 // request the 32-bit variant, transform it here.
4527 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4528 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4529 Inst.getOperand(2).getImm() == ARMCC::AL &&
4530 Inst.getOperand(4).getReg() == ARM::CPSR &&
4531 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4532 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4533 // The operands aren't the same for tMOV[S]r... (no cc_out)
4534 MCInst TmpInst;
4535 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4536 TmpInst.addOperand(Inst.getOperand(0));
4537 TmpInst.addOperand(Inst.getOperand(1));
4538 TmpInst.addOperand(Inst.getOperand(2));
4539 TmpInst.addOperand(Inst.getOperand(3));
4540 Inst = TmpInst;
4541 }
4542 break;
4543 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004544 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004545 case ARM::t2SXTB:
4546 case ARM::t2UXTH:
4547 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004548 // If we can use the 16-bit encoding and the user didn't explicitly
4549 // request the 32-bit variant, transform it here.
4550 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4551 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4552 Inst.getOperand(2).getImm() == 0 &&
4553 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4554 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004555 unsigned NewOpc;
4556 switch (Inst.getOpcode()) {
4557 default: llvm_unreachable("Illegal opcode!");
4558 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4559 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4560 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4561 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4562 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004563 // The operands aren't the same for thumb1 (no rotate operand).
4564 MCInst TmpInst;
4565 TmpInst.setOpcode(NewOpc);
4566 TmpInst.addOperand(Inst.getOperand(0));
4567 TmpInst.addOperand(Inst.getOperand(1));
4568 TmpInst.addOperand(Inst.getOperand(3));
4569 TmpInst.addOperand(Inst.getOperand(4));
4570 Inst = TmpInst;
4571 }
4572 break;
4573 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004574 case ARM::t2IT: {
4575 // The mask bits for all but the first condition are represented as
4576 // the low bit of the condition code value implies 't'. We currently
4577 // always have 1 implies 't', so XOR toggle the bits if the low bit
4578 // of the condition code is zero. The encoding also expects the low
4579 // bit of the condition to be encoded as bit 4 of the mask operand,
4580 // so mask that in if needed
4581 MCOperand &MO = Inst.getOperand(1);
4582 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004583 unsigned OrigMask = Mask;
4584 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004585 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004586 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4587 for (unsigned i = 3; i != TZ; --i)
4588 Mask ^= 1 << i;
4589 } else
4590 Mask |= 0x10;
4591 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004592
4593 // Set up the IT block state according to the IT instruction we just
4594 // matched.
4595 assert(!inITBlock() && "nested IT blocks?!");
4596 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4597 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4598 ITState.CurPosition = 0;
4599 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004600 break;
4601 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004602 }
4603}
4604
Jim Grosbach47a0d522011-08-16 20:45:50 +00004605unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4606 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4607 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004608 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004609 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004610 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4611 assert(MCID.hasOptionalDef() &&
4612 "optionally flag setting instruction missing optional def operand");
4613 assert(MCID.NumOperands == Inst.getNumOperands() &&
4614 "operand count mismatch!");
4615 // Find the optional-def operand (cc_out).
4616 unsigned OpNo;
4617 for (OpNo = 0;
4618 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4619 ++OpNo)
4620 ;
4621 // If we're parsing Thumb1, reject it completely.
4622 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4623 return Match_MnemonicFail;
4624 // If we're parsing Thumb2, which form is legal depends on whether we're
4625 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004626 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4627 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004628 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004629 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4630 inITBlock())
4631 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004632 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004633 // Some high-register supporting Thumb1 encodings only allow both registers
4634 // to be from r0-r7 when in Thumb2.
4635 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4636 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4637 isARMLowRegister(Inst.getOperand(2).getReg()))
4638 return Match_RequiresThumb2;
4639 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004640 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004641 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4642 isARMLowRegister(Inst.getOperand(1).getReg()))
4643 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004644 return Match_Success;
4645}
4646
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004647bool ARMAsmParser::
4648MatchAndEmitInstruction(SMLoc IDLoc,
4649 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4650 MCStreamer &Out) {
4651 MCInst Inst;
4652 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004653 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004654 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004655 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004656 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004657 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004658 // Context sensitive operand constraints aren't handled by the matcher,
4659 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004660 if (validateInstruction(Inst, Operands)) {
4661 // Still progress the IT block, otherwise one wrong condition causes
4662 // nasty cascading errors.
4663 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004664 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004665 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004666
Jim Grosbachf8fce712011-08-11 17:35:48 +00004667 // Some instructions need post-processing to, for example, tweak which
4668 // encoding is selected.
4669 processInstruction(Inst, Operands);
4670
Jim Grosbacha1109882011-09-02 23:22:08 +00004671 // Only move forward at the very end so that everything in validate
4672 // and process gets a consistent answer about whether we're in an IT
4673 // block.
4674 forwardITPosition();
4675
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004676 Out.EmitInstruction(Inst);
4677 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004678 case Match_MissingFeature:
4679 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4680 return true;
4681 case Match_InvalidOperand: {
4682 SMLoc ErrorLoc = IDLoc;
4683 if (ErrorInfo != ~0U) {
4684 if (ErrorInfo >= Operands.size())
4685 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004686
Chris Lattnere73d4f82010-10-28 21:41:58 +00004687 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4688 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4689 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004690
Chris Lattnere73d4f82010-10-28 21:41:58 +00004691 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004692 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004693 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004694 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004695 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004696 // The converter function will have already emited a diagnostic.
4697 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004698 case Match_RequiresNotITBlock:
4699 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004700 case Match_RequiresITBlock:
4701 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004702 case Match_RequiresV6:
4703 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4704 case Match_RequiresThumb2:
4705 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004706 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004707
Eric Christopherc223e2b2010-10-29 09:26:59 +00004708 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004709 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004710}
4711
Jim Grosbach1355cf12011-07-26 17:10:22 +00004712/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004713bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4714 StringRef IDVal = DirectiveID.getIdentifier();
4715 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004716 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004717 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004718 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004719 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004720 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004721 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004722 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004723 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004724 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004725 return true;
4726}
4727
Jim Grosbach1355cf12011-07-26 17:10:22 +00004728/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004729/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004730bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004731 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4732 for (;;) {
4733 const MCExpr *Value;
4734 if (getParser().ParseExpression(Value))
4735 return true;
4736
Chris Lattneraaec2052010-01-19 19:46:13 +00004737 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004738
4739 if (getLexer().is(AsmToken::EndOfStatement))
4740 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004741
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004742 // FIXME: Improve diagnostic.
4743 if (getLexer().isNot(AsmToken::Comma))
4744 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004745 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004746 }
4747 }
4748
Sean Callananb9a25b72010-01-19 20:27:46 +00004749 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004750 return false;
4751}
4752
Jim Grosbach1355cf12011-07-26 17:10:22 +00004753/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004754/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004755bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004756 if (getLexer().isNot(AsmToken::EndOfStatement))
4757 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004758 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004759
4760 // TODO: set thumb mode
4761 // TODO: tell the MC streamer the mode
4762 // getParser().getStreamer().Emit???();
4763 return false;
4764}
4765
Jim Grosbach1355cf12011-07-26 17:10:22 +00004766/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004767/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004768bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004769 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4770 bool isMachO = MAI.hasSubsectionsViaSymbols();
4771 StringRef Name;
4772
4773 // Darwin asm has function name after .thumb_func direction
4774 // ELF doesn't
4775 if (isMachO) {
4776 const AsmToken &Tok = Parser.getTok();
4777 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4778 return Error(L, "unexpected token in .thumb_func directive");
4779 Name = Tok.getString();
4780 Parser.Lex(); // Consume the identifier token.
4781 }
4782
Kevin Enderby515d5092009-10-15 20:48:48 +00004783 if (getLexer().isNot(AsmToken::EndOfStatement))
4784 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004785 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004786
Rafael Espindola64695402011-05-16 16:17:21 +00004787 // FIXME: assuming function name will be the line following .thumb_func
4788 if (!isMachO) {
4789 Name = Parser.getTok().getString();
4790 }
4791
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004792 // Mark symbol as a thumb symbol.
4793 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4794 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004795 return false;
4796}
4797
Jim Grosbach1355cf12011-07-26 17:10:22 +00004798/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004799/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004800bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004801 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004802 if (Tok.isNot(AsmToken::Identifier))
4803 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004804 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004805 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004806 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004807 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004808 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004809 else
4810 return Error(L, "unrecognized syntax mode in .syntax directive");
4811
4812 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004813 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004814 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004815
4816 // TODO tell the MC streamer the mode
4817 // getParser().getStreamer().Emit???();
4818 return false;
4819}
4820
Jim Grosbach1355cf12011-07-26 17:10:22 +00004821/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004822/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004823bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004824 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004825 if (Tok.isNot(AsmToken::Integer))
4826 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004827 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004828 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004829 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004830 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004831 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004832 else
4833 return Error(L, "invalid operand to .code directive");
4834
4835 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004836 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004837 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004838
Evan Cheng32869202011-07-08 22:36:29 +00004839 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004840 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004841 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004842 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004843 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004844 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004845 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004846 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004847 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004848
Kevin Enderby515d5092009-10-15 20:48:48 +00004849 return false;
4850}
4851
Sean Callanan90b70972010-04-07 20:29:34 +00004852extern "C" void LLVMInitializeARMAsmLexer();
4853
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004854/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004855extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004856 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4857 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004858 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004859}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004860
Chris Lattner0692ee62010-09-06 19:11:01 +00004861#define GET_REGISTER_MATCHER
4862#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004863#include "ARMGenAsmMatcher.inc"