blob: 7ec3c8e4e1a884efb0a374b4fcccf8287858f2c4 [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 Grosbach460a9052011-10-07 23:56:00 +0000923 bool isVectorIndex8() const {
924 if (Kind != k_VectorIndex) return false;
925 return VectorIndex.Val < 8;
926 }
927 bool isVectorIndex16() const {
928 if (Kind != k_VectorIndex) return false;
929 return VectorIndex.Val < 4;
930 }
931 bool isVectorIndex32() const {
932 if (Kind != k_VectorIndex) return false;
933 return VectorIndex.Val < 2;
934 }
935
Jim Grosbach0e387b22011-10-17 22:26:03 +0000936 bool isNEONi8splat() const {
937 if (Kind != k_Immediate)
938 return false;
939 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
940 // Must be a constant.
941 if (!CE) return false;
942 int64_t Value = CE->getValue();
943 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
944 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000945 return Value >= 0 && Value < 256;
946 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000947
Jim Grosbachea461102011-10-17 23:09:09 +0000948 bool isNEONi16splat() const {
949 if (Kind != k_Immediate)
950 return false;
951 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
952 // Must be a constant.
953 if (!CE) return false;
954 int64_t Value = CE->getValue();
955 // i16 value in the range [0,255] or [0x0100, 0xff00]
956 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
957 }
958
Jim Grosbach6248a542011-10-18 00:22:00 +0000959 bool isNEONi32splat() const {
960 if (Kind != k_Immediate)
961 return false;
962 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
963 // Must be a constant.
964 if (!CE) return false;
965 int64_t Value = CE->getValue();
966 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
967 return (Value >= 0 && Value < 256) ||
968 (Value >= 0x0100 && Value <= 0xff00) ||
969 (Value >= 0x010000 && Value <= 0xff0000) ||
970 (Value >= 0x01000000 && Value <= 0xff000000);
971 }
972
973 bool isNEONi32vmov() const {
974 if (Kind != k_Immediate)
975 return false;
976 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
977 // Must be a constant.
978 if (!CE) return false;
979 int64_t Value = CE->getValue();
980 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
981 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
982 return (Value >= 0 && Value < 256) ||
983 (Value >= 0x0100 && Value <= 0xff00) ||
984 (Value >= 0x010000 && Value <= 0xff0000) ||
985 (Value >= 0x01000000 && Value <= 0xff000000) ||
986 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
987 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
988 }
989
Jim Grosbachf2f5bc62011-10-18 16:18:11 +0000990 bool isNEONi64splat() 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 uint64_t Value = CE->getValue();
997 // i64 value with each byte being either 0 or 0xff.
998 for (unsigned i = 0; i < 8; ++i)
999 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1000 return true;
1001 }
1002
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001003 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001004 // Add as immediates when possible. Null MCExpr = 0.
1005 if (Expr == 0)
1006 Inst.addOperand(MCOperand::CreateImm(0));
1007 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001008 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1009 else
1010 Inst.addOperand(MCOperand::CreateExpr(Expr));
1011 }
1012
Daniel Dunbar8462b302010-08-11 06:36:53 +00001013 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001014 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001015 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001016 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1017 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001018 }
1019
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001020 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1021 assert(N == 1 && "Invalid number of operands!");
1022 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1023 }
1024
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001025 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1026 assert(N == 1 && "Invalid number of operands!");
1027 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1028 }
1029
1030 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1031 assert(N == 1 && "Invalid number of operands!");
1032 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1033 }
1034
Jim Grosbach89df9962011-08-26 21:43:41 +00001035 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1036 assert(N == 1 && "Invalid number of operands!");
1037 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1038 }
1039
1040 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1041 assert(N == 1 && "Invalid number of operands!");
1042 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1043 }
1044
Jim Grosbachd67641b2010-12-06 18:21:12 +00001045 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1046 assert(N == 1 && "Invalid number of operands!");
1047 Inst.addOperand(MCOperand::CreateReg(getReg()));
1048 }
1049
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001050 void addRegOperands(MCInst &Inst, unsigned N) const {
1051 assert(N == 1 && "Invalid number of operands!");
1052 Inst.addOperand(MCOperand::CreateReg(getReg()));
1053 }
1054
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001055 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001056 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001057 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1058 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1059 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001060 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001061 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001062 }
1063
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001064 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001065 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001066 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1067 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001068 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001069 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001070 }
1071
Jim Grosbach580f4a92011-07-25 22:20:28 +00001072 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001073 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001074 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1075 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001076 }
1077
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001078 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001079 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001080 const SmallVectorImpl<unsigned> &RegList = getRegList();
1081 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001082 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1083 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001084 }
1085
Bill Wendling0f630752010-11-17 04:32:08 +00001086 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1087 addRegListOperands(Inst, N);
1088 }
1089
1090 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1091 addRegListOperands(Inst, N);
1092 }
1093
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001094 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1095 assert(N == 1 && "Invalid number of operands!");
1096 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1097 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1098 }
1099
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001100 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1101 assert(N == 1 && "Invalid number of operands!");
1102 // Munge the lsb/width into a bitfield mask.
1103 unsigned lsb = Bitfield.LSB;
1104 unsigned width = Bitfield.Width;
1105 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1106 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1107 (32 - (lsb + width)));
1108 Inst.addOperand(MCOperand::CreateImm(Mask));
1109 }
1110
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001111 void addImmOperands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
1113 addExpr(Inst, getImm());
1114 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001115
Jim Grosbach9d390362011-10-03 23:38:36 +00001116 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!");
1118 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1119 }
1120
Jim Grosbacha77295d2011-09-08 22:07:06 +00001121 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
1123 // FIXME: We really want to scale the value here, but the LDRD/STRD
1124 // instruction don't encode operands that way yet.
1125 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1126 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1127 }
1128
Jim Grosbach72f39f82011-08-24 21:22:15 +00001129 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
1131 // The immediate is scaled by four in the encoding and is stored
1132 // in the MCInst as such. Lop off the low two bits here.
1133 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1134 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1135 }
1136
1137 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1138 assert(N == 1 && "Invalid number of operands!");
1139 // The immediate is scaled by four in the encoding and is stored
1140 // in the MCInst as such. Lop off the low two bits here.
1141 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1142 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1143 }
1144
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001145 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1146 assert(N == 1 && "Invalid number of operands!");
1147 addExpr(Inst, getImm());
1148 }
1149
Jim Grosbach83ab0702011-07-13 22:01:08 +00001150 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1151 assert(N == 1 && "Invalid number of operands!");
1152 addExpr(Inst, getImm());
1153 }
1154
1155 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1156 assert(N == 1 && "Invalid number of operands!");
1157 addExpr(Inst, getImm());
1158 }
1159
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001160 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 addExpr(Inst, getImm());
1163 }
1164
Jim Grosbachf4943352011-07-25 23:09:14 +00001165 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
1167 // The constant encodes as the immediate-1, and we store in the instruction
1168 // the bits as encoded, so subtract off one here.
1169 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1170 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1171 }
1172
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001173 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1174 assert(N == 1 && "Invalid number of operands!");
1175 // The constant encodes as the immediate-1, and we store in the instruction
1176 // the bits as encoded, so subtract off one here.
1177 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1178 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1179 }
1180
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001181 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1182 assert(N == 1 && "Invalid number of operands!");
1183 addExpr(Inst, getImm());
1184 }
1185
Jim Grosbachffa32252011-07-19 19:13:28 +00001186 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188 addExpr(Inst, getImm());
1189 }
1190
Jim Grosbached838482011-07-26 16:24:27 +00001191 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1192 assert(N == 1 && "Invalid number of operands!");
1193 addExpr(Inst, getImm());
1194 }
1195
Jim Grosbach70939ee2011-08-17 21:51:27 +00001196 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
1198 // The constant encodes as the immediate, except for 32, which encodes as
1199 // zero.
1200 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1201 unsigned Imm = CE->getValue();
1202 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1203 }
1204
Jim Grosbachf6c05252011-07-21 17:23:04 +00001205 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1206 assert(N == 1 && "Invalid number of operands!");
1207 addExpr(Inst, getImm());
1208 }
1209
1210 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 1 && "Invalid number of operands!");
1212 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1213 // the instruction as well.
1214 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1215 int Val = CE->getValue();
1216 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1217 }
1218
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001219 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 1 && "Invalid number of operands!");
1221 addExpr(Inst, getImm());
1222 }
1223
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001224 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1225 assert(N == 1 && "Invalid number of operands!");
1226 addExpr(Inst, getImm());
1227 }
1228
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001229 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1230 assert(N == 1 && "Invalid number of operands!");
1231 addExpr(Inst, getImm());
1232 }
1233
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001234 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1235 assert(N == 1 && "Invalid number of operands!");
1236 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1237 }
1238
Jim Grosbach7ce05792011-08-03 23:50:40 +00001239 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1240 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001241 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001242 }
1243
Jim Grosbach57dcb852011-10-11 17:29:55 +00001244 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 2 && "Invalid number of operands!");
1246 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1247 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1248 }
1249
Jim Grosbach7ce05792011-08-03 23:50:40 +00001250 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1251 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001252 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1253 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001254 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1255 // Special case for #-0
1256 if (Val == INT32_MIN) Val = 0;
1257 if (Val < 0) Val = -Val;
1258 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1259 } else {
1260 // For register offset, we encode the shift type and negation flag
1261 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001262 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1263 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001264 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001265 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1266 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001267 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001268 }
1269
Jim Grosbach039c2e12011-08-04 23:01:30 +00001270 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1271 assert(N == 2 && "Invalid number of operands!");
1272 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1273 assert(CE && "non-constant AM2OffsetImm operand!");
1274 int32_t Val = CE->getValue();
1275 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1276 // Special case for #-0
1277 if (Val == INT32_MIN) Val = 0;
1278 if (Val < 0) Val = -Val;
1279 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1280 Inst.addOperand(MCOperand::CreateReg(0));
1281 Inst.addOperand(MCOperand::CreateImm(Val));
1282 }
1283
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001284 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1285 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001286 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1287 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001288 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1289 // Special case for #-0
1290 if (Val == INT32_MIN) Val = 0;
1291 if (Val < 0) Val = -Val;
1292 Val = ARM_AM::getAM3Opc(AddSub, Val);
1293 } else {
1294 // For register offset, we encode the shift type and negation flag
1295 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001296 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001297 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001298 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1299 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001300 Inst.addOperand(MCOperand::CreateImm(Val));
1301 }
1302
1303 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1304 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001305 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001306 int32_t Val =
1307 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1308 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1309 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001310 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001311 }
1312
1313 // Constant offset.
1314 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1315 int32_t Val = CE->getValue();
1316 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1317 // Special case for #-0
1318 if (Val == INT32_MIN) Val = 0;
1319 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001320 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001321 Inst.addOperand(MCOperand::CreateReg(0));
1322 Inst.addOperand(MCOperand::CreateImm(Val));
1323 }
1324
Jim Grosbach7ce05792011-08-03 23:50:40 +00001325 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1326 assert(N == 2 && "Invalid number of operands!");
1327 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001328 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001329 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1330 // Special case for #-0
1331 if (Val == INT32_MIN) Val = 0;
1332 if (Val < 0) Val = -Val;
1333 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001334 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001335 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001336 }
1337
Jim Grosbacha77295d2011-09-08 22:07:06 +00001338 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1339 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001340 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1341 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001342 Inst.addOperand(MCOperand::CreateImm(Val));
1343 }
1344
Jim Grosbachb6aed502011-09-09 18:37:27 +00001345 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1346 assert(N == 2 && "Invalid number of operands!");
1347 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001348 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1349 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001350 Inst.addOperand(MCOperand::CreateImm(Val));
1351 }
1352
Jim Grosbach7ce05792011-08-03 23:50:40 +00001353 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1354 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001355 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1356 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001357 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001358 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001359
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001360 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1361 addMemImm8OffsetOperands(Inst, N);
1362 }
1363
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001364 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001365 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001366 }
1367
1368 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 2 && "Invalid number of operands!");
1370 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001371 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001372 addExpr(Inst, getImm());
1373 Inst.addOperand(MCOperand::CreateImm(0));
1374 return;
1375 }
1376
1377 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001378 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1379 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001380 Inst.addOperand(MCOperand::CreateImm(Val));
1381 }
1382
Jim Grosbach7ce05792011-08-03 23:50:40 +00001383 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001385 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001386 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001387 addExpr(Inst, getImm());
1388 Inst.addOperand(MCOperand::CreateImm(0));
1389 return;
1390 }
1391
1392 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001393 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1394 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001395 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001396 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001397
Jim Grosbach7f739be2011-09-19 22:21:13 +00001398 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1399 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001400 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1401 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001402 }
1403
1404 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001406 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1407 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001408 }
1409
Jim Grosbach7ce05792011-08-03 23:50:40 +00001410 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1411 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001412 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1413 Memory.ShiftImm, Memory.ShiftType);
1414 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1415 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001416 Inst.addOperand(MCOperand::CreateImm(Val));
1417 }
1418
Jim Grosbachab899c12011-09-07 23:10:15 +00001419 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001421 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1422 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1423 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001424 }
1425
Jim Grosbach7ce05792011-08-03 23:50:40 +00001426 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1427 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001428 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1429 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001430 }
1431
Jim Grosbach60f91a32011-08-19 17:55:24 +00001432 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1433 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001434 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1435 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001436 Inst.addOperand(MCOperand::CreateImm(Val));
1437 }
1438
Jim Grosbach38466302011-08-19 18:55:51 +00001439 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1440 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001441 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1442 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001443 Inst.addOperand(MCOperand::CreateImm(Val));
1444 }
1445
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001446 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1447 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001448 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1449 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001450 Inst.addOperand(MCOperand::CreateImm(Val));
1451 }
1452
Jim Grosbachecd85892011-08-19 18:13:48 +00001453 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1454 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001455 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1456 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001457 Inst.addOperand(MCOperand::CreateImm(Val));
1458 }
1459
Jim Grosbach7ce05792011-08-03 23:50:40 +00001460 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1463 assert(CE && "non-constant post-idx-imm8 operand!");
1464 int Imm = CE->getValue();
1465 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001466 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001467 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1468 Inst.addOperand(MCOperand::CreateImm(Imm));
1469 }
1470
Jim Grosbach2bd01182011-10-11 21:55:36 +00001471 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1472 assert(N == 1 && "Invalid number of operands!");
1473 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1474 assert(CE && "non-constant post-idx-imm8s4 operand!");
1475 int Imm = CE->getValue();
1476 bool isAdd = Imm >= 0;
1477 if (Imm == INT32_MIN) Imm = 0;
1478 // Immediate is scaled by 4.
1479 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1480 Inst.addOperand(MCOperand::CreateImm(Imm));
1481 }
1482
Jim Grosbach7ce05792011-08-03 23:50:40 +00001483 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 2 && "Invalid number of operands!");
1485 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001486 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1487 }
1488
1489 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1490 assert(N == 2 && "Invalid number of operands!");
1491 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1492 // The sign, shift type, and shift amount are encoded in a single operand
1493 // using the AM2 encoding helpers.
1494 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1495 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1496 PostIdxReg.ShiftTy);
1497 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001498 }
1499
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001500 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1501 assert(N == 1 && "Invalid number of operands!");
1502 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1503 }
1504
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001505 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1506 assert(N == 1 && "Invalid number of operands!");
1507 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1508 }
1509
Jim Grosbach862019c2011-10-18 23:02:30 +00001510 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1511 assert(N == 1 && "Invalid number of operands!");
1512 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1513 }
1514
Jim Grosbach280dfad2011-10-21 18:54:25 +00001515 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1516 assert(N == 1 && "Invalid number of operands!");
1517 // Only the first register actually goes on the instruction. The rest
1518 // are implied by the opcode.
1519 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1520 }
1521
Jim Grosbach460a9052011-10-07 23:56:00 +00001522 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1525 }
1526
1527 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1528 assert(N == 1 && "Invalid number of operands!");
1529 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1530 }
1531
1532 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1535 }
1536
Jim Grosbach0e387b22011-10-17 22:26:03 +00001537 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1538 assert(N == 1 && "Invalid number of operands!");
1539 // The immediate encodes the type of constant as well as the value.
1540 // Mask in that this is an i8 splat.
1541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1542 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1543 }
1544
Jim Grosbachea461102011-10-17 23:09:09 +00001545 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1546 assert(N == 1 && "Invalid number of operands!");
1547 // The immediate encodes the type of constant as well as the value.
1548 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1549 unsigned Value = CE->getValue();
1550 if (Value >= 256)
1551 Value = (Value >> 8) | 0xa00;
1552 else
1553 Value |= 0x800;
1554 Inst.addOperand(MCOperand::CreateImm(Value));
1555 }
1556
Jim Grosbach6248a542011-10-18 00:22:00 +00001557 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1558 assert(N == 1 && "Invalid number of operands!");
1559 // The immediate encodes the type of constant as well as the value.
1560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1561 unsigned Value = CE->getValue();
1562 if (Value >= 256 && Value <= 0xff00)
1563 Value = (Value >> 8) | 0x200;
1564 else if (Value > 0xffff && Value <= 0xff0000)
1565 Value = (Value >> 16) | 0x400;
1566 else if (Value > 0xffffff)
1567 Value = (Value >> 24) | 0x600;
1568 Inst.addOperand(MCOperand::CreateImm(Value));
1569 }
1570
1571 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1572 assert(N == 1 && "Invalid number of operands!");
1573 // The immediate encodes the type of constant as well as the value.
1574 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1575 unsigned Value = CE->getValue();
1576 if (Value >= 256 && Value <= 0xffff)
1577 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1578 else if (Value > 0xffff && Value <= 0xffffff)
1579 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1580 else if (Value > 0xffffff)
1581 Value = (Value >> 24) | 0x600;
1582 Inst.addOperand(MCOperand::CreateImm(Value));
1583 }
1584
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001585 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1586 assert(N == 1 && "Invalid number of operands!");
1587 // The immediate encodes the type of constant as well as the value.
1588 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1589 uint64_t Value = CE->getValue();
1590 unsigned Imm = 0;
1591 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1592 Imm |= (Value & 1) << i;
1593 }
1594 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1595 }
1596
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001597 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001598
Jim Grosbach89df9962011-08-26 21:43:41 +00001599 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001600 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001601 Op->ITMask.Mask = Mask;
1602 Op->StartLoc = S;
1603 Op->EndLoc = S;
1604 return Op;
1605 }
1606
Chris Lattner3a697562010-10-28 17:20:03 +00001607 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001608 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001609 Op->CC.Val = CC;
1610 Op->StartLoc = S;
1611 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001612 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001613 }
1614
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001615 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001616 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001617 Op->Cop.Val = CopVal;
1618 Op->StartLoc = S;
1619 Op->EndLoc = S;
1620 return Op;
1621 }
1622
1623 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001624 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001625 Op->Cop.Val = CopVal;
1626 Op->StartLoc = S;
1627 Op->EndLoc = S;
1628 return Op;
1629 }
1630
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001631 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1632 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1633 Op->Cop.Val = Val;
1634 Op->StartLoc = S;
1635 Op->EndLoc = E;
1636 return Op;
1637 }
1638
Jim Grosbachd67641b2010-12-06 18:21:12 +00001639 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001640 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001641 Op->Reg.RegNum = RegNum;
1642 Op->StartLoc = S;
1643 Op->EndLoc = S;
1644 return Op;
1645 }
1646
Chris Lattner3a697562010-10-28 17:20:03 +00001647 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001648 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001649 Op->Tok.Data = Str.data();
1650 Op->Tok.Length = Str.size();
1651 Op->StartLoc = S;
1652 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001653 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001654 }
1655
Bill Wendling50d0f582010-11-18 23:43:05 +00001656 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001657 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001658 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001659 Op->StartLoc = S;
1660 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001661 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001662 }
1663
Jim Grosbache8606dc2011-07-13 17:50:29 +00001664 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1665 unsigned SrcReg,
1666 unsigned ShiftReg,
1667 unsigned ShiftImm,
1668 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001669 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001670 Op->RegShiftedReg.ShiftTy = ShTy;
1671 Op->RegShiftedReg.SrcReg = SrcReg;
1672 Op->RegShiftedReg.ShiftReg = ShiftReg;
1673 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001674 Op->StartLoc = S;
1675 Op->EndLoc = E;
1676 return Op;
1677 }
1678
Owen Anderson92a20222011-07-21 18:54:16 +00001679 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1680 unsigned SrcReg,
1681 unsigned ShiftImm,
1682 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001683 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001684 Op->RegShiftedImm.ShiftTy = ShTy;
1685 Op->RegShiftedImm.SrcReg = SrcReg;
1686 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001687 Op->StartLoc = S;
1688 Op->EndLoc = E;
1689 return Op;
1690 }
1691
Jim Grosbach580f4a92011-07-25 22:20:28 +00001692 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001693 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001694 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001695 Op->ShifterImm.isASR = isASR;
1696 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001697 Op->StartLoc = S;
1698 Op->EndLoc = E;
1699 return Op;
1700 }
1701
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001702 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001703 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001704 Op->RotImm.Imm = Imm;
1705 Op->StartLoc = S;
1706 Op->EndLoc = E;
1707 return Op;
1708 }
1709
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001710 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1711 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001712 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001713 Op->Bitfield.LSB = LSB;
1714 Op->Bitfield.Width = Width;
1715 Op->StartLoc = S;
1716 Op->EndLoc = E;
1717 return Op;
1718 }
1719
Bill Wendling7729e062010-11-09 22:44:22 +00001720 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001721 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001722 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001723 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001724
Jim Grosbachd300b942011-09-13 22:56:44 +00001725 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001726 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001727 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001728 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001729 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001730
1731 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001732 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001733 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001734 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001735 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001736 Op->StartLoc = StartLoc;
1737 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001738 return Op;
1739 }
1740
Jim Grosbach862019c2011-10-18 23:02:30 +00001741 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1742 SMLoc S, SMLoc E) {
1743 ARMOperand *Op = new ARMOperand(k_VectorList);
1744 Op->VectorList.RegNum = RegNum;
1745 Op->VectorList.Count = Count;
1746 Op->StartLoc = S;
1747 Op->EndLoc = E;
1748 return Op;
1749 }
1750
Jim Grosbach460a9052011-10-07 23:56:00 +00001751 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1752 MCContext &Ctx) {
1753 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1754 Op->VectorIndex.Val = Idx;
1755 Op->StartLoc = S;
1756 Op->EndLoc = E;
1757 return Op;
1758 }
1759
Chris Lattner3a697562010-10-28 17:20:03 +00001760 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001761 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001762 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001763 Op->StartLoc = S;
1764 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001765 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001766 }
1767
Jim Grosbach9d390362011-10-03 23:38:36 +00001768 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001769 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001770 Op->FPImm.Val = Val;
1771 Op->StartLoc = S;
1772 Op->EndLoc = S;
1773 return Op;
1774 }
1775
Jim Grosbach7ce05792011-08-03 23:50:40 +00001776 static ARMOperand *CreateMem(unsigned BaseRegNum,
1777 const MCConstantExpr *OffsetImm,
1778 unsigned OffsetRegNum,
1779 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001780 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001781 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001782 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001783 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001784 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001785 Op->Memory.BaseRegNum = BaseRegNum;
1786 Op->Memory.OffsetImm = OffsetImm;
1787 Op->Memory.OffsetRegNum = OffsetRegNum;
1788 Op->Memory.ShiftType = ShiftType;
1789 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001790 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001791 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001792 Op->StartLoc = S;
1793 Op->EndLoc = E;
1794 return Op;
1795 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001796
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001797 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1798 ARM_AM::ShiftOpc ShiftTy,
1799 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001800 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001801 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001802 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001803 Op->PostIdxReg.isAdd = isAdd;
1804 Op->PostIdxReg.ShiftTy = ShiftTy;
1805 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001806 Op->StartLoc = S;
1807 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001808 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001809 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001810
1811 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001812 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001813 Op->MBOpt.Val = Opt;
1814 Op->StartLoc = S;
1815 Op->EndLoc = S;
1816 return Op;
1817 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001818
1819 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001820 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001821 Op->IFlags.Val = IFlags;
1822 Op->StartLoc = S;
1823 Op->EndLoc = S;
1824 return Op;
1825 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001826
1827 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001828 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001829 Op->MMask.Val = MMask;
1830 Op->StartLoc = S;
1831 Op->EndLoc = S;
1832 return Op;
1833 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001834};
1835
1836} // end anonymous namespace.
1837
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001838void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001839 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001840 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001841 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1842 << ") >";
1843 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001844 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001845 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001846 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001847 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001848 OS << "<ccout " << getReg() << ">";
1849 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001850 case k_ITCondMask: {
Jim Grosbach89df9962011-08-26 21:43:41 +00001851 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1852 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1853 "(tee)", "(eee)" };
1854 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1855 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1856 break;
1857 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001858 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001859 OS << "<coprocessor number: " << getCoproc() << ">";
1860 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001861 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001862 OS << "<coprocessor register: " << getCoproc() << ">";
1863 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001864 case k_CoprocOption:
1865 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1866 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001867 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001868 OS << "<mask: " << getMSRMask() << ">";
1869 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001870 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001871 getImm()->print(OS);
1872 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001873 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001874 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1875 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001876 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001877 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001878 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001879 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001880 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001881 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001882 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1883 << PostIdxReg.RegNum;
1884 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1885 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1886 << PostIdxReg.ShiftImm;
1887 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001888 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001889 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001890 OS << "<ARM_PROC::";
1891 unsigned IFlags = getProcIFlags();
1892 for (int i=2; i >= 0; --i)
1893 if (IFlags & (1 << i))
1894 OS << ARM_PROC::IFlagsToString(1 << i);
1895 OS << ">";
1896 break;
1897 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001898 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001899 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001900 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001901 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001902 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1903 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001904 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001905 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001906 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001907 << RegShiftedReg.SrcReg
1908 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1909 << ", " << RegShiftedReg.ShiftReg << ", "
1910 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001911 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001912 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001913 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001914 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001915 << RegShiftedImm.SrcReg
1916 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1917 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001918 << ">";
1919 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001920 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001921 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1922 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001923 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001924 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1925 << ", width: " << Bitfield.Width << ">";
1926 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001927 case k_RegisterList:
1928 case k_DPRRegisterList:
1929 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001930 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001931
Bill Wendling5fa22a12010-11-09 23:28:44 +00001932 const SmallVectorImpl<unsigned> &RegList = getRegList();
1933 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001934 I = RegList.begin(), E = RegList.end(); I != E; ) {
1935 OS << *I;
1936 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001937 }
1938
1939 OS << ">";
1940 break;
1941 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001942 case k_VectorList:
1943 OS << "<vector_list " << VectorList.Count << " * "
1944 << VectorList.RegNum << ">";
1945 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001946 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001947 OS << "'" << getToken() << "'";
1948 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001949 case k_VectorIndex:
1950 OS << "<vectorindex " << getVectorIndex() << ">";
1951 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001952 }
1953}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001954
1955/// @name Auto-generated Match Functions
1956/// {
1957
1958static unsigned MatchRegisterName(StringRef Name);
1959
1960/// }
1961
Bob Wilson69df7232011-02-03 21:46:10 +00001962bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1963 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001964 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001965
1966 return (RegNo == (unsigned)-1);
1967}
1968
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001969/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001970/// and if it is a register name the token is eaten and the register number is
1971/// returned. Otherwise return -1.
1972///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001973int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001974 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001975 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001976
Chris Lattnere5658fa2010-10-30 04:09:10 +00001977 // FIXME: Validate register for the current architecture; we have to do
1978 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00001979 std::string upperCase = Tok.getString().str();
1980 std::string lowerCase = LowercaseString(upperCase);
1981 unsigned RegNum = MatchRegisterName(lowerCase);
1982 if (!RegNum) {
1983 RegNum = StringSwitch<unsigned>(lowerCase)
1984 .Case("r13", ARM::SP)
1985 .Case("r14", ARM::LR)
1986 .Case("r15", ARM::PC)
1987 .Case("ip", ARM::R12)
1988 .Default(0);
1989 }
1990 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00001991
Chris Lattnere5658fa2010-10-30 04:09:10 +00001992 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00001993
Chris Lattnere5658fa2010-10-30 04:09:10 +00001994 return RegNum;
1995}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001996
Jim Grosbach19906722011-07-13 18:49:30 +00001997// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1998// If a recoverable error occurs, return 1. If an irrecoverable error
1999// occurs, return -1. An irrecoverable error is one where tokens have been
2000// consumed in the process of trying to parse the shifter (i.e., when it is
2001// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002002int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002003 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2004 SMLoc S = Parser.getTok().getLoc();
2005 const AsmToken &Tok = Parser.getTok();
2006 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2007
2008 std::string upperCase = Tok.getString().str();
2009 std::string lowerCase = LowercaseString(upperCase);
2010 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2011 .Case("lsl", ARM_AM::lsl)
2012 .Case("lsr", ARM_AM::lsr)
2013 .Case("asr", ARM_AM::asr)
2014 .Case("ror", ARM_AM::ror)
2015 .Case("rrx", ARM_AM::rrx)
2016 .Default(ARM_AM::no_shift);
2017
2018 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002019 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002020
Jim Grosbache8606dc2011-07-13 17:50:29 +00002021 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002022
Jim Grosbache8606dc2011-07-13 17:50:29 +00002023 // The source register for the shift has already been added to the
2024 // operand list, so we need to pop it off and combine it into the shifted
2025 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002026 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002027 if (!PrevOp->isReg())
2028 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2029 int SrcReg = PrevOp->getReg();
2030 int64_t Imm = 0;
2031 int ShiftReg = 0;
2032 if (ShiftTy == ARM_AM::rrx) {
2033 // RRX Doesn't have an explicit shift amount. The encoder expects
2034 // the shift register to be the same as the source register. Seems odd,
2035 // but OK.
2036 ShiftReg = SrcReg;
2037 } else {
2038 // Figure out if this is shifted by a constant or a register (for non-RRX).
2039 if (Parser.getTok().is(AsmToken::Hash)) {
2040 Parser.Lex(); // Eat hash.
2041 SMLoc ImmLoc = Parser.getTok().getLoc();
2042 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002043 if (getParser().ParseExpression(ShiftExpr)) {
2044 Error(ImmLoc, "invalid immediate shift value");
2045 return -1;
2046 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002047 // The expression must be evaluatable as an immediate.
2048 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002049 if (!CE) {
2050 Error(ImmLoc, "invalid immediate shift value");
2051 return -1;
2052 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002053 // Range check the immediate.
2054 // lsl, ror: 0 <= imm <= 31
2055 // lsr, asr: 0 <= imm <= 32
2056 Imm = CE->getValue();
2057 if (Imm < 0 ||
2058 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2059 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002060 Error(ImmLoc, "immediate shift value out of range");
2061 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002062 }
2063 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002064 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002065 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002066 if (ShiftReg == -1) {
2067 Error (L, "expected immediate or register in shift operand");
2068 return -1;
2069 }
2070 } else {
2071 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002072 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002073 return -1;
2074 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002075 }
2076
Owen Anderson92a20222011-07-21 18:54:16 +00002077 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2078 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002079 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002080 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002081 else
2082 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2083 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002084
Jim Grosbach19906722011-07-13 18:49:30 +00002085 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002086}
2087
2088
Bill Wendling50d0f582010-11-18 23:43:05 +00002089/// Try to parse a register name. The token must be an Identifier when called.
2090/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2091/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002092///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002093/// TODO this is likely to change to allow different register types and or to
2094/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002095bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002096tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002097 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002098 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002099 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002100 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002101
Bill Wendling50d0f582010-11-18 23:43:05 +00002102 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002103
Chris Lattnere5658fa2010-10-30 04:09:10 +00002104 const AsmToken &ExclaimTok = Parser.getTok();
2105 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002106 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2107 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002108 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002109 return false;
2110 }
2111
2112 // Also check for an index operand. This is only legal for vector registers,
2113 // but that'll get caught OK in operand matching, so we don't need to
2114 // explicitly filter everything else out here.
2115 if (Parser.getTok().is(AsmToken::LBrac)) {
2116 SMLoc SIdx = Parser.getTok().getLoc();
2117 Parser.Lex(); // Eat left bracket token.
2118
2119 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002120 if (getParser().ParseExpression(ImmVal))
2121 return MatchOperand_ParseFail;
2122 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2123 if (!MCE) {
2124 TokError("immediate value expected for vector index");
2125 return MatchOperand_ParseFail;
2126 }
2127
2128 SMLoc E = Parser.getTok().getLoc();
2129 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2130 Error(E, "']' expected");
2131 return MatchOperand_ParseFail;
2132 }
2133
2134 Parser.Lex(); // Eat right bracket token.
2135
2136 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2137 SIdx, E,
2138 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002139 }
2140
Bill Wendling50d0f582010-11-18 23:43:05 +00002141 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002142}
2143
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002144/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2145/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2146/// "c5", ...
2147static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002148 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2149 // but efficient.
2150 switch (Name.size()) {
2151 default: break;
2152 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002153 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002154 return -1;
2155 switch (Name[1]) {
2156 default: return -1;
2157 case '0': return 0;
2158 case '1': return 1;
2159 case '2': return 2;
2160 case '3': return 3;
2161 case '4': return 4;
2162 case '5': return 5;
2163 case '6': return 6;
2164 case '7': return 7;
2165 case '8': return 8;
2166 case '9': return 9;
2167 }
2168 break;
2169 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002170 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002171 return -1;
2172 switch (Name[2]) {
2173 default: return -1;
2174 case '0': return 10;
2175 case '1': return 11;
2176 case '2': return 12;
2177 case '3': return 13;
2178 case '4': return 14;
2179 case '5': return 15;
2180 }
2181 break;
2182 }
2183
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002184 return -1;
2185}
2186
Jim Grosbach89df9962011-08-26 21:43:41 +00002187/// parseITCondCode - Try to parse a condition code for an IT instruction.
2188ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2189parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2190 SMLoc S = Parser.getTok().getLoc();
2191 const AsmToken &Tok = Parser.getTok();
2192 if (!Tok.is(AsmToken::Identifier))
2193 return MatchOperand_NoMatch;
2194 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2195 .Case("eq", ARMCC::EQ)
2196 .Case("ne", ARMCC::NE)
2197 .Case("hs", ARMCC::HS)
2198 .Case("cs", ARMCC::HS)
2199 .Case("lo", ARMCC::LO)
2200 .Case("cc", ARMCC::LO)
2201 .Case("mi", ARMCC::MI)
2202 .Case("pl", ARMCC::PL)
2203 .Case("vs", ARMCC::VS)
2204 .Case("vc", ARMCC::VC)
2205 .Case("hi", ARMCC::HI)
2206 .Case("ls", ARMCC::LS)
2207 .Case("ge", ARMCC::GE)
2208 .Case("lt", ARMCC::LT)
2209 .Case("gt", ARMCC::GT)
2210 .Case("le", ARMCC::LE)
2211 .Case("al", ARMCC::AL)
2212 .Default(~0U);
2213 if (CC == ~0U)
2214 return MatchOperand_NoMatch;
2215 Parser.Lex(); // Eat the token.
2216
2217 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2218
2219 return MatchOperand_Success;
2220}
2221
Jim Grosbach43904292011-07-25 20:14:50 +00002222/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002223/// token must be an Identifier when called, and if it is a coprocessor
2224/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002225ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002226parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002227 SMLoc S = Parser.getTok().getLoc();
2228 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002229 if (Tok.isNot(AsmToken::Identifier))
2230 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002231
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002232 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002233 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002234 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002235
2236 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002237 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002238 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002239}
2240
Jim Grosbach43904292011-07-25 20:14:50 +00002241/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002242/// token must be an Identifier when called, and if it is a coprocessor
2243/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002244ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002245parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002246 SMLoc S = Parser.getTok().getLoc();
2247 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002248 if (Tok.isNot(AsmToken::Identifier))
2249 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002250
2251 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2252 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002253 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002254
2255 Parser.Lex(); // Eat identifier token.
2256 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002257 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002258}
2259
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002260/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2261/// coproc_option : '{' imm0_255 '}'
2262ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2263parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2264 SMLoc S = Parser.getTok().getLoc();
2265
2266 // If this isn't a '{', this isn't a coprocessor immediate operand.
2267 if (Parser.getTok().isNot(AsmToken::LCurly))
2268 return MatchOperand_NoMatch;
2269 Parser.Lex(); // Eat the '{'
2270
2271 const MCExpr *Expr;
2272 SMLoc Loc = Parser.getTok().getLoc();
2273 if (getParser().ParseExpression(Expr)) {
2274 Error(Loc, "illegal expression");
2275 return MatchOperand_ParseFail;
2276 }
2277 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2278 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2279 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2280 return MatchOperand_ParseFail;
2281 }
2282 int Val = CE->getValue();
2283
2284 // Check for and consume the closing '}'
2285 if (Parser.getTok().isNot(AsmToken::RCurly))
2286 return MatchOperand_ParseFail;
2287 SMLoc E = Parser.getTok().getLoc();
2288 Parser.Lex(); // Eat the '}'
2289
2290 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2291 return MatchOperand_Success;
2292}
2293
Jim Grosbachd0588e22011-09-14 18:08:35 +00002294// For register list parsing, we need to map from raw GPR register numbering
2295// to the enumeration values. The enumeration values aren't sorted by
2296// register number due to our using "sp", "lr" and "pc" as canonical names.
2297static unsigned getNextRegister(unsigned Reg) {
2298 // If this is a GPR, we need to do it manually, otherwise we can rely
2299 // on the sort ordering of the enumeration since the other reg-classes
2300 // are sane.
2301 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2302 return Reg + 1;
2303 switch(Reg) {
2304 default: assert(0 && "Invalid GPR number!");
2305 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2306 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2307 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2308 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2309 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2310 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2311 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2312 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2313 }
2314}
2315
2316/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002317bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002318parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002319 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002320 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002321 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002322 Parser.Lex(); // Eat '{' token.
2323 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002324
Jim Grosbachd0588e22011-09-14 18:08:35 +00002325 // Check the first register in the list to see what register class
2326 // this is a list of.
2327 int Reg = tryParseRegister();
2328 if (Reg == -1)
2329 return Error(RegLoc, "register expected");
2330
2331 MCRegisterClass *RC;
2332 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2333 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2334 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2335 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2336 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2337 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2338 else
2339 return Error(RegLoc, "invalid register in register list");
2340
2341 // The reglist instructions have at most 16 registers, so reserve
2342 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002343 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002344 // Store the first register.
2345 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002346
Jim Grosbachd0588e22011-09-14 18:08:35 +00002347 // This starts immediately after the first register token in the list,
2348 // so we can see either a comma or a minus (range separator) as a legal
2349 // next token.
2350 while (Parser.getTok().is(AsmToken::Comma) ||
2351 Parser.getTok().is(AsmToken::Minus)) {
2352 if (Parser.getTok().is(AsmToken::Minus)) {
2353 Parser.Lex(); // Eat the comma.
2354 SMLoc EndLoc = Parser.getTok().getLoc();
2355 int EndReg = tryParseRegister();
2356 if (EndReg == -1)
2357 return Error(EndLoc, "register expected");
2358 // If the register is the same as the start reg, there's nothing
2359 // more to do.
2360 if (Reg == EndReg)
2361 continue;
2362 // The register must be in the same register class as the first.
2363 if (!RC->contains(EndReg))
2364 return Error(EndLoc, "invalid register in register list");
2365 // Ranges must go from low to high.
2366 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2367 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002368
Jim Grosbachd0588e22011-09-14 18:08:35 +00002369 // Add all the registers in the range to the register list.
2370 while (Reg != EndReg) {
2371 Reg = getNextRegister(Reg);
2372 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2373 }
2374 continue;
2375 }
2376 Parser.Lex(); // Eat the comma.
2377 RegLoc = Parser.getTok().getLoc();
2378 int OldReg = Reg;
2379 Reg = tryParseRegister();
2380 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002381 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002382 // The register must be in the same register class as the first.
2383 if (!RC->contains(Reg))
2384 return Error(RegLoc, "invalid register in register list");
2385 // List must be monotonically increasing.
2386 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2387 return Error(RegLoc, "register list not in ascending order");
2388 // VFP register lists must also be contiguous.
2389 // It's OK to use the enumeration values directly here rather, as the
2390 // VFP register classes have the enum sorted properly.
2391 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2392 Reg != OldReg + 1)
2393 return Error(RegLoc, "non-contiguous register range");
2394 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002395 }
2396
Jim Grosbachd0588e22011-09-14 18:08:35 +00002397 SMLoc E = Parser.getTok().getLoc();
2398 if (Parser.getTok().isNot(AsmToken::RCurly))
2399 return Error(E, "'}' expected");
2400 Parser.Lex(); // Eat '}' token.
2401
Bill Wendling50d0f582010-11-18 23:43:05 +00002402 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2403 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002404}
2405
Jim Grosbach862019c2011-10-18 23:02:30 +00002406// parse a vector register list
2407ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2408parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2409 if(Parser.getTok().isNot(AsmToken::LCurly))
2410 return MatchOperand_NoMatch;
2411
2412 SMLoc S = Parser.getTok().getLoc();
2413 Parser.Lex(); // Eat '{' token.
2414 SMLoc RegLoc = Parser.getTok().getLoc();
2415
2416 int Reg = tryParseRegister();
2417 if (Reg == -1) {
2418 Error(RegLoc, "register expected");
2419 return MatchOperand_ParseFail;
2420 }
2421
2422 unsigned FirstReg = Reg;
2423 unsigned Count = 1;
2424 while (Parser.getTok().is(AsmToken::Comma)) {
2425 Parser.Lex(); // Eat the comma.
2426 RegLoc = Parser.getTok().getLoc();
2427 int OldReg = Reg;
2428 Reg = tryParseRegister();
2429 if (Reg == -1) {
2430 Error(RegLoc, "register expected");
2431 return MatchOperand_ParseFail;
2432 }
2433 // vector register lists must also be contiguous.
2434 // It's OK to use the enumeration values directly here rather, as the
2435 // VFP register classes have the enum sorted properly.
2436 if (Reg != OldReg + 1) {
2437 Error(RegLoc, "non-contiguous register range");
2438 return MatchOperand_ParseFail;
2439 }
2440
2441 ++Count;
2442 }
2443
2444 SMLoc E = Parser.getTok().getLoc();
2445 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2446 Error(E, "'}' expected");
2447 return MatchOperand_ParseFail;
2448 }
2449 Parser.Lex(); // Eat '}' token.
2450
2451 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2452 return MatchOperand_Success;
2453}
2454
Jim Grosbach43904292011-07-25 20:14:50 +00002455/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002456ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002457parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002458 SMLoc S = Parser.getTok().getLoc();
2459 const AsmToken &Tok = Parser.getTok();
2460 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2461 StringRef OptStr = Tok.getString();
2462
2463 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2464 .Case("sy", ARM_MB::SY)
2465 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002466 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002467 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002468 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002469 .Case("ishst", ARM_MB::ISHST)
2470 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002471 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002472 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002473 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002474 .Case("osh", ARM_MB::OSH)
2475 .Case("oshst", ARM_MB::OSHST)
2476 .Default(~0U);
2477
2478 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002479 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002480
2481 Parser.Lex(); // Eat identifier token.
2482 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002483 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002484}
2485
Jim Grosbach43904292011-07-25 20:14:50 +00002486/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002487ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002488parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002489 SMLoc S = Parser.getTok().getLoc();
2490 const AsmToken &Tok = Parser.getTok();
2491 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2492 StringRef IFlagsStr = Tok.getString();
2493
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002494 // An iflags string of "none" is interpreted to mean that none of the AIF
2495 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002496 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002497 if (IFlagsStr != "none") {
2498 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2499 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2500 .Case("a", ARM_PROC::A)
2501 .Case("i", ARM_PROC::I)
2502 .Case("f", ARM_PROC::F)
2503 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002504
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002505 // If some specific iflag is already set, it means that some letter is
2506 // present more than once, this is not acceptable.
2507 if (Flag == ~0U || (IFlags & Flag))
2508 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002509
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002510 IFlags |= Flag;
2511 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002512 }
2513
2514 Parser.Lex(); // Eat identifier token.
2515 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2516 return MatchOperand_Success;
2517}
2518
Jim Grosbach43904292011-07-25 20:14:50 +00002519/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002520ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002521parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002522 SMLoc S = Parser.getTok().getLoc();
2523 const AsmToken &Tok = Parser.getTok();
2524 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2525 StringRef Mask = Tok.getString();
2526
James Molloyacad68d2011-09-28 14:21:38 +00002527 if (isMClass()) {
2528 // See ARMv6-M 10.1.1
2529 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2530 .Case("apsr", 0)
2531 .Case("iapsr", 1)
2532 .Case("eapsr", 2)
2533 .Case("xpsr", 3)
2534 .Case("ipsr", 5)
2535 .Case("epsr", 6)
2536 .Case("iepsr", 7)
2537 .Case("msp", 8)
2538 .Case("psp", 9)
2539 .Case("primask", 16)
2540 .Case("basepri", 17)
2541 .Case("basepri_max", 18)
2542 .Case("faultmask", 19)
2543 .Case("control", 20)
2544 .Default(~0U);
2545
2546 if (FlagsVal == ~0U)
2547 return MatchOperand_NoMatch;
2548
2549 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2550 // basepri, basepri_max and faultmask only valid for V7m.
2551 return MatchOperand_NoMatch;
2552
2553 Parser.Lex(); // Eat identifier token.
2554 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2555 return MatchOperand_Success;
2556 }
2557
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002558 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2559 size_t Start = 0, Next = Mask.find('_');
2560 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002561 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002562 if (Next != StringRef::npos)
2563 Flags = Mask.slice(Next+1, Mask.size());
2564
2565 // FlagsVal contains the complete mask:
2566 // 3-0: Mask
2567 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2568 unsigned FlagsVal = 0;
2569
2570 if (SpecReg == "apsr") {
2571 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002572 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002573 .Case("g", 0x4) // same as CPSR_s
2574 .Case("nzcvqg", 0xc) // same as CPSR_fs
2575 .Default(~0U);
2576
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002577 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002578 if (!Flags.empty())
2579 return MatchOperand_NoMatch;
2580 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002581 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002582 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002583 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002584 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2585 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002586 for (int i = 0, e = Flags.size(); i != e; ++i) {
2587 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2588 .Case("c", 1)
2589 .Case("x", 2)
2590 .Case("s", 4)
2591 .Case("f", 8)
2592 .Default(~0U);
2593
2594 // If some specific flag is already set, it means that some letter is
2595 // present more than once, this is not acceptable.
2596 if (FlagsVal == ~0U || (FlagsVal & Flag))
2597 return MatchOperand_NoMatch;
2598 FlagsVal |= Flag;
2599 }
2600 } else // No match for special register.
2601 return MatchOperand_NoMatch;
2602
Owen Anderson7784f1d2011-10-21 18:43:28 +00002603 // Special register without flags is NOT equivalent to "fc" flags.
2604 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2605 // two lines would enable gas compatibility at the expense of breaking
2606 // round-tripping.
2607 //
2608 // if (!FlagsVal)
2609 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002610
2611 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2612 if (SpecReg == "spsr")
2613 FlagsVal |= 16;
2614
2615 Parser.Lex(); // Eat identifier token.
2616 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2617 return MatchOperand_Success;
2618}
2619
Jim Grosbachf6c05252011-07-21 17:23:04 +00002620ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2621parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2622 int Low, int High) {
2623 const AsmToken &Tok = Parser.getTok();
2624 if (Tok.isNot(AsmToken::Identifier)) {
2625 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2626 return MatchOperand_ParseFail;
2627 }
2628 StringRef ShiftName = Tok.getString();
2629 std::string LowerOp = LowercaseString(Op);
2630 std::string UpperOp = UppercaseString(Op);
2631 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2632 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2633 return MatchOperand_ParseFail;
2634 }
2635 Parser.Lex(); // Eat shift type token.
2636
2637 // There must be a '#' and a shift amount.
2638 if (Parser.getTok().isNot(AsmToken::Hash)) {
2639 Error(Parser.getTok().getLoc(), "'#' expected");
2640 return MatchOperand_ParseFail;
2641 }
2642 Parser.Lex(); // Eat hash token.
2643
2644 const MCExpr *ShiftAmount;
2645 SMLoc Loc = Parser.getTok().getLoc();
2646 if (getParser().ParseExpression(ShiftAmount)) {
2647 Error(Loc, "illegal expression");
2648 return MatchOperand_ParseFail;
2649 }
2650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2651 if (!CE) {
2652 Error(Loc, "constant expression expected");
2653 return MatchOperand_ParseFail;
2654 }
2655 int Val = CE->getValue();
2656 if (Val < Low || Val > High) {
2657 Error(Loc, "immediate value out of range");
2658 return MatchOperand_ParseFail;
2659 }
2660
2661 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2662
2663 return MatchOperand_Success;
2664}
2665
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002666ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2667parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2668 const AsmToken &Tok = Parser.getTok();
2669 SMLoc S = Tok.getLoc();
2670 if (Tok.isNot(AsmToken::Identifier)) {
2671 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2672 return MatchOperand_ParseFail;
2673 }
2674 int Val = StringSwitch<int>(Tok.getString())
2675 .Case("be", 1)
2676 .Case("le", 0)
2677 .Default(-1);
2678 Parser.Lex(); // Eat the token.
2679
2680 if (Val == -1) {
2681 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2682 return MatchOperand_ParseFail;
2683 }
2684 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2685 getContext()),
2686 S, Parser.getTok().getLoc()));
2687 return MatchOperand_Success;
2688}
2689
Jim Grosbach580f4a92011-07-25 22:20:28 +00002690/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2691/// instructions. Legal values are:
2692/// lsl #n 'n' in [0,31]
2693/// asr #n 'n' in [1,32]
2694/// n == 32 encoded as n == 0.
2695ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2696parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2697 const AsmToken &Tok = Parser.getTok();
2698 SMLoc S = Tok.getLoc();
2699 if (Tok.isNot(AsmToken::Identifier)) {
2700 Error(S, "shift operator 'asr' or 'lsl' expected");
2701 return MatchOperand_ParseFail;
2702 }
2703 StringRef ShiftName = Tok.getString();
2704 bool isASR;
2705 if (ShiftName == "lsl" || ShiftName == "LSL")
2706 isASR = false;
2707 else if (ShiftName == "asr" || ShiftName == "ASR")
2708 isASR = true;
2709 else {
2710 Error(S, "shift operator 'asr' or 'lsl' expected");
2711 return MatchOperand_ParseFail;
2712 }
2713 Parser.Lex(); // Eat the operator.
2714
2715 // A '#' and a shift amount.
2716 if (Parser.getTok().isNot(AsmToken::Hash)) {
2717 Error(Parser.getTok().getLoc(), "'#' expected");
2718 return MatchOperand_ParseFail;
2719 }
2720 Parser.Lex(); // Eat hash token.
2721
2722 const MCExpr *ShiftAmount;
2723 SMLoc E = Parser.getTok().getLoc();
2724 if (getParser().ParseExpression(ShiftAmount)) {
2725 Error(E, "malformed shift expression");
2726 return MatchOperand_ParseFail;
2727 }
2728 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2729 if (!CE) {
2730 Error(E, "shift amount must be an immediate");
2731 return MatchOperand_ParseFail;
2732 }
2733
2734 int64_t Val = CE->getValue();
2735 if (isASR) {
2736 // Shift amount must be in [1,32]
2737 if (Val < 1 || Val > 32) {
2738 Error(E, "'asr' shift amount must be in range [1,32]");
2739 return MatchOperand_ParseFail;
2740 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002741 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2742 if (isThumb() && Val == 32) {
2743 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2744 return MatchOperand_ParseFail;
2745 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002746 if (Val == 32) Val = 0;
2747 } else {
2748 // Shift amount must be in [1,32]
2749 if (Val < 0 || Val > 31) {
2750 Error(E, "'lsr' shift amount must be in range [0,31]");
2751 return MatchOperand_ParseFail;
2752 }
2753 }
2754
2755 E = Parser.getTok().getLoc();
2756 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2757
2758 return MatchOperand_Success;
2759}
2760
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002761/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2762/// of instructions. Legal values are:
2763/// ror #n 'n' in {0, 8, 16, 24}
2764ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2765parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2766 const AsmToken &Tok = Parser.getTok();
2767 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002768 if (Tok.isNot(AsmToken::Identifier))
2769 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002770 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002771 if (ShiftName != "ror" && ShiftName != "ROR")
2772 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002773 Parser.Lex(); // Eat the operator.
2774
2775 // A '#' and a rotate amount.
2776 if (Parser.getTok().isNot(AsmToken::Hash)) {
2777 Error(Parser.getTok().getLoc(), "'#' expected");
2778 return MatchOperand_ParseFail;
2779 }
2780 Parser.Lex(); // Eat hash token.
2781
2782 const MCExpr *ShiftAmount;
2783 SMLoc E = Parser.getTok().getLoc();
2784 if (getParser().ParseExpression(ShiftAmount)) {
2785 Error(E, "malformed rotate expression");
2786 return MatchOperand_ParseFail;
2787 }
2788 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2789 if (!CE) {
2790 Error(E, "rotate amount must be an immediate");
2791 return MatchOperand_ParseFail;
2792 }
2793
2794 int64_t Val = CE->getValue();
2795 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2796 // normally, zero is represented in asm by omitting the rotate operand
2797 // entirely.
2798 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2799 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2800 return MatchOperand_ParseFail;
2801 }
2802
2803 E = Parser.getTok().getLoc();
2804 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2805
2806 return MatchOperand_Success;
2807}
2808
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002809ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2810parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2811 SMLoc S = Parser.getTok().getLoc();
2812 // The bitfield descriptor is really two operands, the LSB and the width.
2813 if (Parser.getTok().isNot(AsmToken::Hash)) {
2814 Error(Parser.getTok().getLoc(), "'#' expected");
2815 return MatchOperand_ParseFail;
2816 }
2817 Parser.Lex(); // Eat hash token.
2818
2819 const MCExpr *LSBExpr;
2820 SMLoc E = Parser.getTok().getLoc();
2821 if (getParser().ParseExpression(LSBExpr)) {
2822 Error(E, "malformed immediate expression");
2823 return MatchOperand_ParseFail;
2824 }
2825 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2826 if (!CE) {
2827 Error(E, "'lsb' operand must be an immediate");
2828 return MatchOperand_ParseFail;
2829 }
2830
2831 int64_t LSB = CE->getValue();
2832 // The LSB must be in the range [0,31]
2833 if (LSB < 0 || LSB > 31) {
2834 Error(E, "'lsb' operand must be in the range [0,31]");
2835 return MatchOperand_ParseFail;
2836 }
2837 E = Parser.getTok().getLoc();
2838
2839 // Expect another immediate operand.
2840 if (Parser.getTok().isNot(AsmToken::Comma)) {
2841 Error(Parser.getTok().getLoc(), "too few operands");
2842 return MatchOperand_ParseFail;
2843 }
2844 Parser.Lex(); // Eat hash token.
2845 if (Parser.getTok().isNot(AsmToken::Hash)) {
2846 Error(Parser.getTok().getLoc(), "'#' expected");
2847 return MatchOperand_ParseFail;
2848 }
2849 Parser.Lex(); // Eat hash token.
2850
2851 const MCExpr *WidthExpr;
2852 if (getParser().ParseExpression(WidthExpr)) {
2853 Error(E, "malformed immediate expression");
2854 return MatchOperand_ParseFail;
2855 }
2856 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2857 if (!CE) {
2858 Error(E, "'width' operand must be an immediate");
2859 return MatchOperand_ParseFail;
2860 }
2861
2862 int64_t Width = CE->getValue();
2863 // The LSB must be in the range [1,32-lsb]
2864 if (Width < 1 || Width > 32 - LSB) {
2865 Error(E, "'width' operand must be in the range [1,32-lsb]");
2866 return MatchOperand_ParseFail;
2867 }
2868 E = Parser.getTok().getLoc();
2869
2870 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2871
2872 return MatchOperand_Success;
2873}
2874
Jim Grosbach7ce05792011-08-03 23:50:40 +00002875ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2876parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2877 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002878 // postidx_reg := '+' register {, shift}
2879 // | '-' register {, shift}
2880 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002881
2882 // This method must return MatchOperand_NoMatch without consuming any tokens
2883 // in the case where there is no match, as other alternatives take other
2884 // parse methods.
2885 AsmToken Tok = Parser.getTok();
2886 SMLoc S = Tok.getLoc();
2887 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002888 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002889 int Reg = -1;
2890 if (Tok.is(AsmToken::Plus)) {
2891 Parser.Lex(); // Eat the '+' token.
2892 haveEaten = true;
2893 } else if (Tok.is(AsmToken::Minus)) {
2894 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002895 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002896 haveEaten = true;
2897 }
2898 if (Parser.getTok().is(AsmToken::Identifier))
2899 Reg = tryParseRegister();
2900 if (Reg == -1) {
2901 if (!haveEaten)
2902 return MatchOperand_NoMatch;
2903 Error(Parser.getTok().getLoc(), "register expected");
2904 return MatchOperand_ParseFail;
2905 }
2906 SMLoc E = Parser.getTok().getLoc();
2907
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002908 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2909 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002910 if (Parser.getTok().is(AsmToken::Comma)) {
2911 Parser.Lex(); // Eat the ','.
2912 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2913 return MatchOperand_ParseFail;
2914 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002915
2916 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2917 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002918
2919 return MatchOperand_Success;
2920}
2921
Jim Grosbach251bf252011-08-10 21:56:18 +00002922ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2923parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2924 // Check for a post-index addressing register operand. Specifically:
2925 // am3offset := '+' register
2926 // | '-' register
2927 // | register
2928 // | # imm
2929 // | # + imm
2930 // | # - imm
2931
2932 // This method must return MatchOperand_NoMatch without consuming any tokens
2933 // in the case where there is no match, as other alternatives take other
2934 // parse methods.
2935 AsmToken Tok = Parser.getTok();
2936 SMLoc S = Tok.getLoc();
2937
2938 // Do immediates first, as we always parse those if we have a '#'.
2939 if (Parser.getTok().is(AsmToken::Hash)) {
2940 Parser.Lex(); // Eat the '#'.
2941 // Explicitly look for a '-', as we need to encode negative zero
2942 // differently.
2943 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2944 const MCExpr *Offset;
2945 if (getParser().ParseExpression(Offset))
2946 return MatchOperand_ParseFail;
2947 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2948 if (!CE) {
2949 Error(S, "constant expression expected");
2950 return MatchOperand_ParseFail;
2951 }
2952 SMLoc E = Tok.getLoc();
2953 // Negative zero is encoded as the flag value INT32_MIN.
2954 int32_t Val = CE->getValue();
2955 if (isNegative && Val == 0)
2956 Val = INT32_MIN;
2957
2958 Operands.push_back(
2959 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2960
2961 return MatchOperand_Success;
2962 }
2963
2964
2965 bool haveEaten = false;
2966 bool isAdd = true;
2967 int Reg = -1;
2968 if (Tok.is(AsmToken::Plus)) {
2969 Parser.Lex(); // Eat the '+' token.
2970 haveEaten = true;
2971 } else if (Tok.is(AsmToken::Minus)) {
2972 Parser.Lex(); // Eat the '-' token.
2973 isAdd = false;
2974 haveEaten = true;
2975 }
2976 if (Parser.getTok().is(AsmToken::Identifier))
2977 Reg = tryParseRegister();
2978 if (Reg == -1) {
2979 if (!haveEaten)
2980 return MatchOperand_NoMatch;
2981 Error(Parser.getTok().getLoc(), "register expected");
2982 return MatchOperand_ParseFail;
2983 }
2984 SMLoc E = Parser.getTok().getLoc();
2985
2986 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2987 0, S, E));
2988
2989 return MatchOperand_Success;
2990}
2991
Jim Grosbacha77295d2011-09-08 22:07:06 +00002992/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2993/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2994/// when they refer multiple MIOperands inside a single one.
2995bool ARMAsmParser::
2996cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2997 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2998 // Rt, Rt2
2999 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3000 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3001 // Create a writeback register dummy placeholder.
3002 Inst.addOperand(MCOperand::CreateReg(0));
3003 // addr
3004 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3005 // pred
3006 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3007 return true;
3008}
3009
3010/// cvtT2StrdPre - Convert parsed operands to MCInst.
3011/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3012/// when they refer multiple MIOperands inside a single one.
3013bool ARMAsmParser::
3014cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3015 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3016 // Create a writeback register dummy placeholder.
3017 Inst.addOperand(MCOperand::CreateReg(0));
3018 // Rt, Rt2
3019 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3020 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3021 // addr
3022 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3023 // pred
3024 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3025 return true;
3026}
3027
Jim Grosbacheeec0252011-09-08 00:39:19 +00003028/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3029/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3030/// when they refer multiple MIOperands inside a single one.
3031bool ARMAsmParser::
3032cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3033 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3034 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3035
3036 // Create a writeback register dummy placeholder.
3037 Inst.addOperand(MCOperand::CreateImm(0));
3038
3039 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3040 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3041 return true;
3042}
3043
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003044/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3045/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3046/// when they refer multiple MIOperands inside a single one.
3047bool ARMAsmParser::
3048cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3049 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3050 // Create a writeback register dummy placeholder.
3051 Inst.addOperand(MCOperand::CreateImm(0));
3052 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3053 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3054 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3055 return true;
3056}
3057
Jim Grosbach1355cf12011-07-26 17:10:22 +00003058/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003059/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3060/// when they refer multiple MIOperands inside a single one.
3061bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003062cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003063 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3064 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3065
3066 // Create a writeback register dummy placeholder.
3067 Inst.addOperand(MCOperand::CreateImm(0));
3068
Jim Grosbach7ce05792011-08-03 23:50:40 +00003069 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003070 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3071 return true;
3072}
3073
Owen Anderson9ab0f252011-08-26 20:43:14 +00003074/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3075/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3076/// when they refer multiple MIOperands inside a single one.
3077bool ARMAsmParser::
3078cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3079 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3080 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3081
3082 // Create a writeback register dummy placeholder.
3083 Inst.addOperand(MCOperand::CreateImm(0));
3084
3085 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3086 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3087 return true;
3088}
3089
3090
Jim Grosbach548340c2011-08-11 19:22:40 +00003091/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3092/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3093/// when they refer multiple MIOperands inside a single one.
3094bool ARMAsmParser::
3095cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3096 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3097 // Create a writeback register dummy placeholder.
3098 Inst.addOperand(MCOperand::CreateImm(0));
3099 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3100 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3101 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3102 return true;
3103}
3104
Jim Grosbach1355cf12011-07-26 17:10:22 +00003105/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003106/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3107/// when they refer multiple MIOperands inside a single one.
3108bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003109cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003110 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3111 // Create a writeback register dummy placeholder.
3112 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003113 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3114 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3115 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003116 return true;
3117}
3118
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003119/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3120/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3121/// when they refer multiple MIOperands inside a single one.
3122bool ARMAsmParser::
3123cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3124 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3125 // Create a writeback register dummy placeholder.
3126 Inst.addOperand(MCOperand::CreateImm(0));
3127 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3128 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3129 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3130 return true;
3131}
3132
Jim Grosbach7ce05792011-08-03 23:50:40 +00003133/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3134/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3135/// when they refer multiple MIOperands inside a single one.
3136bool ARMAsmParser::
3137cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3138 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3139 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003140 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003141 // Create a writeback register dummy placeholder.
3142 Inst.addOperand(MCOperand::CreateImm(0));
3143 // addr
3144 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3145 // offset
3146 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3147 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003148 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3149 return true;
3150}
3151
Jim Grosbach7ce05792011-08-03 23:50:40 +00003152/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003153/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3154/// when they refer multiple MIOperands inside a single one.
3155bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003156cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3157 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3158 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003159 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003160 // Create a writeback register dummy placeholder.
3161 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003162 // addr
3163 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3164 // offset
3165 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3166 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003167 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3168 return true;
3169}
3170
Jim Grosbach7ce05792011-08-03 23:50:40 +00003171/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003172/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3173/// when they refer multiple MIOperands inside a single one.
3174bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003175cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3176 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003177 // Create a writeback register dummy placeholder.
3178 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003179 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003180 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003181 // addr
3182 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3183 // offset
3184 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3185 // pred
3186 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3187 return true;
3188}
3189
3190/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3191/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3192/// when they refer multiple MIOperands inside a single one.
3193bool ARMAsmParser::
3194cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3195 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3196 // Create a writeback register dummy placeholder.
3197 Inst.addOperand(MCOperand::CreateImm(0));
3198 // Rt
3199 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3200 // addr
3201 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3202 // offset
3203 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3204 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003205 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3206 return true;
3207}
3208
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003209/// cvtLdrdPre - Convert parsed operands to MCInst.
3210/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3211/// when they refer multiple MIOperands inside a single one.
3212bool ARMAsmParser::
3213cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3214 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3215 // Rt, Rt2
3216 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3217 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3218 // Create a writeback register dummy placeholder.
3219 Inst.addOperand(MCOperand::CreateImm(0));
3220 // addr
3221 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3222 // pred
3223 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3224 return true;
3225}
3226
Jim Grosbach14605d12011-08-11 20:28:23 +00003227/// cvtStrdPre - Convert parsed operands to MCInst.
3228/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3229/// when they refer multiple MIOperands inside a single one.
3230bool ARMAsmParser::
3231cvtStrdPre(MCInst &Inst, unsigned Opcode,
3232 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3233 // Create a writeback register dummy placeholder.
3234 Inst.addOperand(MCOperand::CreateImm(0));
3235 // Rt, Rt2
3236 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3237 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3238 // addr
3239 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3240 // pred
3241 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3242 return true;
3243}
3244
Jim Grosbach623a4542011-08-10 22:42:16 +00003245/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3246/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3247/// when they refer multiple MIOperands inside a single one.
3248bool ARMAsmParser::
3249cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3250 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3251 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3252 // Create a writeback register dummy placeholder.
3253 Inst.addOperand(MCOperand::CreateImm(0));
3254 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3255 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3256 return true;
3257}
3258
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003259/// cvtThumbMultiple- Convert parsed operands to MCInst.
3260/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3261/// when they refer multiple MIOperands inside a single one.
3262bool ARMAsmParser::
3263cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3264 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3265 // The second source operand must be the same register as the destination
3266 // operand.
3267 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003268 (((ARMOperand*)Operands[3])->getReg() !=
3269 ((ARMOperand*)Operands[5])->getReg()) &&
3270 (((ARMOperand*)Operands[3])->getReg() !=
3271 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003272 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003273 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003274 return false;
3275 }
3276 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3277 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3278 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003279 // If we have a three-operand form, use that, else the second source operand
3280 // is just the destination operand again.
3281 if (Operands.size() == 6)
3282 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3283 else
3284 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003285 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3286
3287 return true;
3288}
Jim Grosbach623a4542011-08-10 22:42:16 +00003289
Bill Wendlinge7176102010-11-06 22:36:58 +00003290/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003291/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003292bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003293parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003294 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003295 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003296 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003297 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003298 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003299
Sean Callanan18b83232010-01-19 21:44:56 +00003300 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003301 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003302 if (BaseRegNum == -1)
3303 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003304
Daniel Dunbar05710932011-01-18 05:34:17 +00003305 // The next token must either be a comma or a closing bracket.
3306 const AsmToken &Tok = Parser.getTok();
3307 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003308 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003309
Jim Grosbach7ce05792011-08-03 23:50:40 +00003310 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003311 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003312 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003313
Jim Grosbach7ce05792011-08-03 23:50:40 +00003314 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003315 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003316
Jim Grosbachfb12f352011-09-19 18:42:21 +00003317 // If there's a pre-indexing writeback marker, '!', just add it as a token
3318 // operand. It's rather odd, but syntactically valid.
3319 if (Parser.getTok().is(AsmToken::Exclaim)) {
3320 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3321 Parser.Lex(); // Eat the '!'.
3322 }
3323
Jim Grosbach7ce05792011-08-03 23:50:40 +00003324 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003325 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003326
Jim Grosbach7ce05792011-08-03 23:50:40 +00003327 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3328 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003329
Jim Grosbach57dcb852011-10-11 17:29:55 +00003330 // If we have a ':', it's an alignment specifier.
3331 if (Parser.getTok().is(AsmToken::Colon)) {
3332 Parser.Lex(); // Eat the ':'.
3333 E = Parser.getTok().getLoc();
3334
3335 const MCExpr *Expr;
3336 if (getParser().ParseExpression(Expr))
3337 return true;
3338
3339 // The expression has to be a constant. Memory references with relocations
3340 // don't come through here, as they use the <label> forms of the relevant
3341 // instructions.
3342 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3343 if (!CE)
3344 return Error (E, "constant expression expected");
3345
3346 unsigned Align = 0;
3347 switch (CE->getValue()) {
3348 default:
3349 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3350 case 64: Align = 8; break;
3351 case 128: Align = 16; break;
3352 case 256: Align = 32; break;
3353 }
3354
3355 // Now we should have the closing ']'
3356 E = Parser.getTok().getLoc();
3357 if (Parser.getTok().isNot(AsmToken::RBrac))
3358 return Error(E, "']' expected");
3359 Parser.Lex(); // Eat right bracket token.
3360
3361 // Don't worry about range checking the value here. That's handled by
3362 // the is*() predicates.
3363 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3364 ARM_AM::no_shift, 0, Align,
3365 false, S, E));
3366
3367 // If there's a pre-indexing writeback marker, '!', just add it as a token
3368 // operand.
3369 if (Parser.getTok().is(AsmToken::Exclaim)) {
3370 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3371 Parser.Lex(); // Eat the '!'.
3372 }
3373
3374 return false;
3375 }
3376
3377 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003378 // offset.
3379 if (Parser.getTok().is(AsmToken::Hash)) {
3380 Parser.Lex(); // Eat the '#'.
3381 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003382
Owen Anderson0da10cf2011-08-29 19:36:44 +00003383 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003384 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003385 if (getParser().ParseExpression(Offset))
3386 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003387
3388 // The expression has to be a constant. Memory references with relocations
3389 // don't come through here, as they use the <label> forms of the relevant
3390 // instructions.
3391 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3392 if (!CE)
3393 return Error (E, "constant expression expected");
3394
Owen Anderson0da10cf2011-08-29 19:36:44 +00003395 // If the constant was #-0, represent it as INT32_MIN.
3396 int32_t Val = CE->getValue();
3397 if (isNegative && Val == 0)
3398 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3399
Jim Grosbach7ce05792011-08-03 23:50:40 +00003400 // Now we should have the closing ']'
3401 E = Parser.getTok().getLoc();
3402 if (Parser.getTok().isNot(AsmToken::RBrac))
3403 return Error(E, "']' expected");
3404 Parser.Lex(); // Eat right bracket token.
3405
3406 // Don't worry about range checking the value here. That's handled by
3407 // the is*() predicates.
3408 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003409 ARM_AM::no_shift, 0, 0,
3410 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003411
3412 // If there's a pre-indexing writeback marker, '!', just add it as a token
3413 // operand.
3414 if (Parser.getTok().is(AsmToken::Exclaim)) {
3415 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3416 Parser.Lex(); // Eat the '!'.
3417 }
3418
3419 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003420 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003421
3422 // The register offset is optionally preceded by a '+' or '-'
3423 bool isNegative = false;
3424 if (Parser.getTok().is(AsmToken::Minus)) {
3425 isNegative = true;
3426 Parser.Lex(); // Eat the '-'.
3427 } else if (Parser.getTok().is(AsmToken::Plus)) {
3428 // Nothing to do.
3429 Parser.Lex(); // Eat the '+'.
3430 }
3431
3432 E = Parser.getTok().getLoc();
3433 int OffsetRegNum = tryParseRegister();
3434 if (OffsetRegNum == -1)
3435 return Error(E, "register expected");
3436
3437 // If there's a shift operator, handle it.
3438 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003439 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003440 if (Parser.getTok().is(AsmToken::Comma)) {
3441 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003442 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003443 return true;
3444 }
3445
3446 // Now we should have the closing ']'
3447 E = Parser.getTok().getLoc();
3448 if (Parser.getTok().isNot(AsmToken::RBrac))
3449 return Error(E, "']' expected");
3450 Parser.Lex(); // Eat right bracket token.
3451
3452 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003453 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003454 S, E));
3455
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003456 // If there's a pre-indexing writeback marker, '!', just add it as a token
3457 // operand.
3458 if (Parser.getTok().is(AsmToken::Exclaim)) {
3459 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3460 Parser.Lex(); // Eat the '!'.
3461 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003462
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003463 return false;
3464}
3465
Jim Grosbach7ce05792011-08-03 23:50:40 +00003466/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003467/// ( lsl | lsr | asr | ror ) , # shift_amount
3468/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003469/// return true if it parses a shift otherwise it returns false.
3470bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3471 unsigned &Amount) {
3472 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003473 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003474 if (Tok.isNot(AsmToken::Identifier))
3475 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003476 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003477 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003478 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003479 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003480 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003481 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003482 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003483 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003484 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003485 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003486 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003487 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003488 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003489 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003490
Jim Grosbach7ce05792011-08-03 23:50:40 +00003491 // rrx stands alone.
3492 Amount = 0;
3493 if (St != ARM_AM::rrx) {
3494 Loc = Parser.getTok().getLoc();
3495 // A '#' and a shift amount.
3496 const AsmToken &HashTok = Parser.getTok();
3497 if (HashTok.isNot(AsmToken::Hash))
3498 return Error(HashTok.getLoc(), "'#' expected");
3499 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003500
Jim Grosbach7ce05792011-08-03 23:50:40 +00003501 const MCExpr *Expr;
3502 if (getParser().ParseExpression(Expr))
3503 return true;
3504 // Range check the immediate.
3505 // lsl, ror: 0 <= imm <= 31
3506 // lsr, asr: 0 <= imm <= 32
3507 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3508 if (!CE)
3509 return Error(Loc, "shift amount must be an immediate");
3510 int64_t Imm = CE->getValue();
3511 if (Imm < 0 ||
3512 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3513 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3514 return Error(Loc, "immediate shift value out of range");
3515 Amount = Imm;
3516 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003517
3518 return false;
3519}
3520
Jim Grosbach9d390362011-10-03 23:38:36 +00003521/// parseFPImm - A floating point immediate expression operand.
3522ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3523parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3524 SMLoc S = Parser.getTok().getLoc();
3525
3526 if (Parser.getTok().isNot(AsmToken::Hash))
3527 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003528
3529 // Disambiguate the VMOV forms that can accept an FP immediate.
3530 // vmov.f32 <sreg>, #imm
3531 // vmov.f64 <dreg>, #imm
3532 // vmov.f32 <dreg>, #imm @ vector f32x2
3533 // vmov.f32 <qreg>, #imm @ vector f32x4
3534 //
3535 // There are also the NEON VMOV instructions which expect an
3536 // integer constant. Make sure we don't try to parse an FPImm
3537 // for these:
3538 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3539 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3540 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3541 TyOp->getToken() != ".f64"))
3542 return MatchOperand_NoMatch;
3543
Jim Grosbach9d390362011-10-03 23:38:36 +00003544 Parser.Lex(); // Eat the '#'.
3545
3546 // Handle negation, as that still comes through as a separate token.
3547 bool isNegative = false;
3548 if (Parser.getTok().is(AsmToken::Minus)) {
3549 isNegative = true;
3550 Parser.Lex();
3551 }
3552 const AsmToken &Tok = Parser.getTok();
3553 if (Tok.is(AsmToken::Real)) {
3554 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3555 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3556 // If we had a '-' in front, toggle the sign bit.
3557 IntVal ^= (uint64_t)isNegative << 63;
3558 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3559 Parser.Lex(); // Eat the token.
3560 if (Val == -1) {
3561 TokError("floating point value out of range");
3562 return MatchOperand_ParseFail;
3563 }
3564 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3565 return MatchOperand_Success;
3566 }
3567 if (Tok.is(AsmToken::Integer)) {
3568 int64_t Val = Tok.getIntVal();
3569 Parser.Lex(); // Eat the token.
3570 if (Val > 255 || Val < 0) {
3571 TokError("encoded floating point value out of range");
3572 return MatchOperand_ParseFail;
3573 }
3574 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3575 return MatchOperand_Success;
3576 }
3577
3578 TokError("invalid floating point immediate");
3579 return MatchOperand_ParseFail;
3580}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003581/// Parse a arm instruction operand. For now this parses the operand regardless
3582/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003583bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003584 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003585 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003586
3587 // Check if the current operand has a custom associated parser, if so, try to
3588 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003589 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3590 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003591 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003592 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3593 // there was a match, but an error occurred, in which case, just return that
3594 // the operand parsing failed.
3595 if (ResTy == MatchOperand_ParseFail)
3596 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003597
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003598 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003599 default:
3600 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003601 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003602 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003603 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003604 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003605 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003606 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003607 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003608 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003609 else if (Res == -1) // irrecoverable error
3610 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003611 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3612 S = Parser.getTok().getLoc();
3613 Parser.Lex();
3614 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3615 return false;
3616 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003617
3618 // Fall though for the Identifier case that is not a register or a
3619 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003620 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003621 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3622 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003623 // This was not a register so parse other operands that start with an
3624 // identifier (like labels) as expressions and create them as immediates.
3625 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003626 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003627 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003628 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003629 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003630 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3631 return false;
3632 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003633 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003634 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003635 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003636 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003637 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003638 // #42 -> immediate.
3639 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003640 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003641 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003642 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003643 const MCExpr *ImmVal;
3644 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003645 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3647 if (!CE) {
3648 Error(S, "constant expression expected");
3649 return MatchOperand_ParseFail;
3650 }
3651 int32_t Val = CE->getValue();
3652 if (isNegative && Val == 0)
3653 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003654 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003655 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3656 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003657 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003658 case AsmToken::Colon: {
3659 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003660 // FIXME: Check it's an expression prefix,
3661 // e.g. (FOO - :lower16:BAR) isn't legal.
3662 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003663 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003664 return true;
3665
Evan Cheng75972122011-01-13 07:58:56 +00003666 const MCExpr *SubExprVal;
3667 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003668 return true;
3669
Evan Cheng75972122011-01-13 07:58:56 +00003670 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3671 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003672 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003673 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003674 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003675 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003676 }
3677}
3678
Jim Grosbach1355cf12011-07-26 17:10:22 +00003679// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003680// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003681bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003682 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003683
3684 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003685 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003686 Parser.Lex(); // Eat ':'
3687
3688 if (getLexer().isNot(AsmToken::Identifier)) {
3689 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3690 return true;
3691 }
3692
3693 StringRef IDVal = Parser.getTok().getIdentifier();
3694 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003695 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003696 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003697 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003698 } else {
3699 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3700 return true;
3701 }
3702 Parser.Lex();
3703
3704 if (getLexer().isNot(AsmToken::Colon)) {
3705 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3706 return true;
3707 }
3708 Parser.Lex(); // Eat the last ':'
3709 return false;
3710}
3711
Daniel Dunbar352e1482011-01-11 15:59:50 +00003712/// \brief Given a mnemonic, split out possible predication code and carry
3713/// setting letters to form a canonical mnemonic and flags.
3714//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003715// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003716// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003717StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003718 unsigned &PredicationCode,
3719 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003720 unsigned &ProcessorIMod,
3721 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003722 PredicationCode = ARMCC::AL;
3723 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003724 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003725
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003726 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003727 //
3728 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003729 if ((Mnemonic == "movs" && isThumb()) ||
3730 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3731 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3732 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3733 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3734 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3735 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3736 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003737 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003738
Jim Grosbach3f00e312011-07-11 17:09:57 +00003739 // First, split out any predication code. Ignore mnemonics we know aren't
3740 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003741 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003742 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003743 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003744 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003745 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3746 .Case("eq", ARMCC::EQ)
3747 .Case("ne", ARMCC::NE)
3748 .Case("hs", ARMCC::HS)
3749 .Case("cs", ARMCC::HS)
3750 .Case("lo", ARMCC::LO)
3751 .Case("cc", ARMCC::LO)
3752 .Case("mi", ARMCC::MI)
3753 .Case("pl", ARMCC::PL)
3754 .Case("vs", ARMCC::VS)
3755 .Case("vc", ARMCC::VC)
3756 .Case("hi", ARMCC::HI)
3757 .Case("ls", ARMCC::LS)
3758 .Case("ge", ARMCC::GE)
3759 .Case("lt", ARMCC::LT)
3760 .Case("gt", ARMCC::GT)
3761 .Case("le", ARMCC::LE)
3762 .Case("al", ARMCC::AL)
3763 .Default(~0U);
3764 if (CC != ~0U) {
3765 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3766 PredicationCode = CC;
3767 }
Bill Wendling52925b62010-10-29 23:50:21 +00003768 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003769
Daniel Dunbar352e1482011-01-11 15:59:50 +00003770 // Next, determine if we have a carry setting bit. We explicitly ignore all
3771 // the instructions we know end in 's'.
3772 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003773 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003774 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3775 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3776 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003777 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3778 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003779 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3780 CarrySetting = true;
3781 }
3782
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003783 // The "cps" instruction can have a interrupt mode operand which is glued into
3784 // the mnemonic. Check if this is the case, split it and parse the imod op
3785 if (Mnemonic.startswith("cps")) {
3786 // Split out any imod code.
3787 unsigned IMod =
3788 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3789 .Case("ie", ARM_PROC::IE)
3790 .Case("id", ARM_PROC::ID)
3791 .Default(~0U);
3792 if (IMod != ~0U) {
3793 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3794 ProcessorIMod = IMod;
3795 }
3796 }
3797
Jim Grosbach89df9962011-08-26 21:43:41 +00003798 // The "it" instruction has the condition mask on the end of the mnemonic.
3799 if (Mnemonic.startswith("it")) {
3800 ITMask = Mnemonic.slice(2, Mnemonic.size());
3801 Mnemonic = Mnemonic.slice(0, 2);
3802 }
3803
Daniel Dunbar352e1482011-01-11 15:59:50 +00003804 return Mnemonic;
3805}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003806
3807/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3808/// inclusion of carry set or predication code operands.
3809//
3810// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003811void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003812getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003813 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003814 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3815 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003816 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003817 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003818 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003819 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003820 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003821 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003822 Mnemonic == "mla" || Mnemonic == "smlal" ||
3823 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003824 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003825 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003826 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003827
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003828 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3829 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3830 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3831 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003832 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3833 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003834 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003835 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3836 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3837 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003838 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3839 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003840 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003841 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003842 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003843 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003844
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003845 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003846 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003847 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003848 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003849 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003850}
3851
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003852bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3853 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003854 // FIXME: This is all horribly hacky. We really need a better way to deal
3855 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003856
3857 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3858 // another does not. Specifically, the MOVW instruction does not. So we
3859 // special case it here and remove the defaulted (non-setting) cc_out
3860 // operand if that's the instruction we're trying to match.
3861 //
3862 // We do this as post-processing of the explicit operands rather than just
3863 // conditionally adding the cc_out in the first place because we need
3864 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003865 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003866 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3867 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3868 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3869 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003870
3871 // Register-register 'add' for thumb does not have a cc_out operand
3872 // when there are only two register operands.
3873 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3874 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3875 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3876 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3877 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003878 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003879 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3880 // have to check the immediate range here since Thumb2 has a variant
3881 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003882 if (((isThumb() && Mnemonic == "add") ||
3883 (isThumbTwo() && Mnemonic == "sub")) &&
3884 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003885 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3886 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3887 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003888 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3889 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3890 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003891 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003892 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3893 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003894 // selecting via the generic "add" mnemonic, so to know that we
3895 // should remove the cc_out operand, we have to explicitly check that
3896 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003897 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3898 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003899 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3900 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3901 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3902 // Nest conditions rather than one big 'if' statement for readability.
3903 //
3904 // If either register is a high reg, it's either one of the SP
3905 // variants (handled above) or a 32-bit encoding, so we just
3906 // check against T3.
3907 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3908 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3909 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3910 return false;
3911 // If both registers are low, we're in an IT block, and the immediate is
3912 // in range, we should use encoding T1 instead, which has a cc_out.
3913 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003914 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003915 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3916 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3917 return false;
3918
3919 // Otherwise, we use encoding T4, which does not have a cc_out
3920 // operand.
3921 return true;
3922 }
3923
Jim Grosbach64944f42011-09-14 21:00:40 +00003924 // The thumb2 multiply instruction doesn't have a CCOut register, so
3925 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3926 // use the 16-bit encoding or not.
3927 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3928 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3929 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3930 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3931 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3932 // If the registers aren't low regs, the destination reg isn't the
3933 // same as one of the source regs, or the cc_out operand is zero
3934 // outside of an IT block, we have to use the 32-bit encoding, so
3935 // remove the cc_out operand.
3936 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3937 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3938 !inITBlock() ||
3939 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3940 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3941 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3942 static_cast<ARMOperand*>(Operands[4])->getReg())))
3943 return true;
3944
3945
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003946
Jim Grosbachf69c8042011-08-24 21:42:27 +00003947 // Register-register 'add/sub' for thumb does not have a cc_out operand
3948 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3949 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3950 // right, this will result in better diagnostics (which operand is off)
3951 // anyway.
3952 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3953 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003954 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3955 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3956 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3957 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003958
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003959 return false;
3960}
3961
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003962/// Parse an arm instruction mnemonic followed by its operands.
3963bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3964 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3965 // Create the leading tokens for the mnemonic, split by '.' characters.
3966 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003967 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003968
Daniel Dunbar352e1482011-01-11 15:59:50 +00003969 // Split out the predication code and carry setting flag from the mnemonic.
3970 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003971 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003972 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003973 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003974 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003975 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003976
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003977 // In Thumb1, only the branch (B) instruction can be predicated.
3978 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3979 Parser.EatToEndOfStatement();
3980 return Error(NameLoc, "conditional execution not supported in Thumb1");
3981 }
3982
Jim Grosbachffa32252011-07-19 19:13:28 +00003983 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3984
Jim Grosbach89df9962011-08-26 21:43:41 +00003985 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3986 // is the mask as it will be for the IT encoding if the conditional
3987 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3988 // where the conditional bit0 is zero, the instruction post-processing
3989 // will adjust the mask accordingly.
3990 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003991 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3992 if (ITMask.size() > 3) {
3993 Parser.EatToEndOfStatement();
3994 return Error(Loc, "too many conditions on IT instruction");
3995 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003996 unsigned Mask = 8;
3997 for (unsigned i = ITMask.size(); i != 0; --i) {
3998 char pos = ITMask[i - 1];
3999 if (pos != 't' && pos != 'e') {
4000 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004001 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004002 }
4003 Mask >>= 1;
4004 if (ITMask[i - 1] == 't')
4005 Mask |= 8;
4006 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004007 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004008 }
4009
Jim Grosbachffa32252011-07-19 19:13:28 +00004010 // FIXME: This is all a pretty gross hack. We should automatically handle
4011 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004012
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004013 // Next, add the CCOut and ConditionCode operands, if needed.
4014 //
4015 // For mnemonics which can ever incorporate a carry setting bit or predication
4016 // code, our matching model involves us always generating CCOut and
4017 // ConditionCode operands to match the mnemonic "as written" and then we let
4018 // the matcher deal with finding the right instruction or generating an
4019 // appropriate error.
4020 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004021 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004022
Jim Grosbach33c16a22011-07-14 22:04:21 +00004023 // If we had a carry-set on an instruction that can't do that, issue an
4024 // error.
4025 if (!CanAcceptCarrySet && CarrySetting) {
4026 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004027 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004028 "' can not set flags, but 's' suffix specified");
4029 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004030 // If we had a predication code on an instruction that can't do that, issue an
4031 // error.
4032 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4033 Parser.EatToEndOfStatement();
4034 return Error(NameLoc, "instruction '" + Mnemonic +
4035 "' is not predicable, but condition code specified");
4036 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004037
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004038 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004039 if (CanAcceptCarrySet) {
4040 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004041 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004042 Loc));
4043 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004044
4045 // Add the predication code operand, if necessary.
4046 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004047 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4048 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004049 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004050 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004051 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004052
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004053 // Add the processor imod operand, if necessary.
4054 if (ProcessorIMod) {
4055 Operands.push_back(ARMOperand::CreateImm(
4056 MCConstantExpr::Create(ProcessorIMod, getContext()),
4057 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004058 }
4059
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004060 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004061 while (Next != StringRef::npos) {
4062 Start = Next;
4063 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004064 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004065
Jim Grosbach4d23e992011-08-24 22:19:48 +00004066 // For now, we're only parsing Thumb1 (for the most part), so
4067 // just ignore ".n" qualifiers. We'll use them to restrict
4068 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00004069 if (ExtraToken != ".n") {
4070 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4071 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4072 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004073 }
4074
4075 // Read the remaining operands.
4076 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004077 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004078 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004079 Parser.EatToEndOfStatement();
4080 return true;
4081 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004082
4083 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004084 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004085
4086 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004087 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004088 Parser.EatToEndOfStatement();
4089 return true;
4090 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004091 }
4092 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004093
Chris Lattnercbf8a982010-09-11 16:18:25 +00004094 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004095 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004096 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004097 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004098 }
Bill Wendling146018f2010-11-06 21:42:12 +00004099
Chris Lattner34e53142010-09-08 05:10:46 +00004100 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004101
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004102 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4103 // do and don't have a cc_out optional-def operand. With some spot-checks
4104 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004105 // parse and adjust accordingly before actually matching. We shouldn't ever
4106 // try to remove a cc_out operand that was explicitly set on the the
4107 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4108 // table driven matcher doesn't fit well with the ARM instruction set.
4109 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004110 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4111 Operands.erase(Operands.begin() + 1);
4112 delete Op;
4113 }
4114
Jim Grosbachcf121c32011-07-28 21:57:55 +00004115 // ARM mode 'blx' need special handling, as the register operand version
4116 // is predicable, but the label operand version is not. So, we can't rely
4117 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004118 // a k_CondCode operand in the list. If we're trying to match the label
4119 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004120 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4121 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4122 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4123 Operands.erase(Operands.begin() + 1);
4124 delete Op;
4125 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004126
4127 // The vector-compare-to-zero instructions have a literal token "#0" at
4128 // the end that comes to here as an immediate operand. Convert it to a
4129 // token to play nicely with the matcher.
4130 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4131 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4132 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4133 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4134 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4135 if (CE && CE->getValue() == 0) {
4136 Operands.erase(Operands.begin() + 5);
4137 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4138 delete Op;
4139 }
4140 }
Jim Grosbach68259142011-10-03 22:30:24 +00004141 // VCMP{E} does the same thing, but with a different operand count.
4142 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4143 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4144 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4145 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4146 if (CE && CE->getValue() == 0) {
4147 Operands.erase(Operands.begin() + 4);
4148 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4149 delete Op;
4150 }
4151 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004152 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4153 // end. Convert it to a token here.
4154 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4155 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4156 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4157 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4158 if (CE && CE->getValue() == 0) {
4159 Operands.erase(Operands.begin() + 5);
4160 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4161 delete Op;
4162 }
4163 }
4164
Chris Lattner98986712010-01-14 22:21:20 +00004165 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004166}
4167
Jim Grosbach189610f2011-07-26 18:25:39 +00004168// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004169
4170// return 'true' if register list contains non-low GPR registers,
4171// 'false' otherwise. If Reg is in the register list or is HiReg, set
4172// 'containsReg' to true.
4173static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4174 unsigned HiReg, bool &containsReg) {
4175 containsReg = false;
4176 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4177 unsigned OpReg = Inst.getOperand(i).getReg();
4178 if (OpReg == Reg)
4179 containsReg = true;
4180 // Anything other than a low register isn't legal here.
4181 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4182 return true;
4183 }
4184 return false;
4185}
4186
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004187// Check if the specified regisgter is in the register list of the inst,
4188// starting at the indicated operand number.
4189static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4190 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4191 unsigned OpReg = Inst.getOperand(i).getReg();
4192 if (OpReg == Reg)
4193 return true;
4194 }
4195 return false;
4196}
4197
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004198// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4199// the ARMInsts array) instead. Getting that here requires awkward
4200// API changes, though. Better way?
4201namespace llvm {
4202extern MCInstrDesc ARMInsts[];
4203}
4204static MCInstrDesc &getInstDesc(unsigned Opcode) {
4205 return ARMInsts[Opcode];
4206}
4207
Jim Grosbach189610f2011-07-26 18:25:39 +00004208// FIXME: We would really like to be able to tablegen'erate this.
4209bool ARMAsmParser::
4210validateInstruction(MCInst &Inst,
4211 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004212 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
4213 SMLoc Loc = Operands[0]->getStartLoc();
4214 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004215 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4216 // being allowed in IT blocks, but not being predicable. It just always
4217 // executes.
4218 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004219 unsigned bit = 1;
4220 if (ITState.FirstCond)
4221 ITState.FirstCond = false;
4222 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004223 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004224 // The instruction must be predicable.
4225 if (!MCID.isPredicable())
4226 return Error(Loc, "instructions in IT block must be predicable");
4227 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4228 unsigned ITCond = bit ? ITState.Cond :
4229 ARMCC::getOppositeCondition(ITState.Cond);
4230 if (Cond != ITCond) {
4231 // Find the condition code Operand to get its SMLoc information.
4232 SMLoc CondLoc;
4233 for (unsigned i = 1; i < Operands.size(); ++i)
4234 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4235 CondLoc = Operands[i]->getStartLoc();
4236 return Error(CondLoc, "incorrect condition in IT block; got '" +
4237 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4238 "', but expected '" +
4239 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4240 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004241 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004242 } else if (isThumbTwo() && MCID.isPredicable() &&
4243 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004244 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4245 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004246 return Error(Loc, "predicated instructions must be in IT block");
4247
Jim Grosbach189610f2011-07-26 18:25:39 +00004248 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004249 case ARM::LDRD:
4250 case ARM::LDRD_PRE:
4251 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004252 case ARM::LDREXD: {
4253 // Rt2 must be Rt + 1.
4254 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4255 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4256 if (Rt2 != Rt + 1)
4257 return Error(Operands[3]->getStartLoc(),
4258 "destination operands must be sequential");
4259 return false;
4260 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004261 case ARM::STRD: {
4262 // Rt2 must be Rt + 1.
4263 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4264 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4265 if (Rt2 != Rt + 1)
4266 return Error(Operands[3]->getStartLoc(),
4267 "source operands must be sequential");
4268 return false;
4269 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004270 case ARM::STRD_PRE:
4271 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004272 case ARM::STREXD: {
4273 // Rt2 must be Rt + 1.
4274 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4275 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4276 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004277 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004278 "source operands must be sequential");
4279 return false;
4280 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004281 case ARM::SBFX:
4282 case ARM::UBFX: {
4283 // width must be in range [1, 32-lsb]
4284 unsigned lsb = Inst.getOperand(2).getImm();
4285 unsigned widthm1 = Inst.getOperand(3).getImm();
4286 if (widthm1 >= 32 - lsb)
4287 return Error(Operands[5]->getStartLoc(),
4288 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004289 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004290 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004291 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004292 // If we're parsing Thumb2, the .w variant is available and handles
4293 // most cases that are normally illegal for a Thumb1 LDM
4294 // instruction. We'll make the transformation in processInstruction()
4295 // if necessary.
4296 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004297 // Thumb LDM instructions are writeback iff the base register is not
4298 // in the register list.
4299 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004300 bool hasWritebackToken =
4301 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4302 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004303 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004304 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004305 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4306 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004307 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004308 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004309 return Error(Operands[2]->getStartLoc(),
4310 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004311 // If we should not have writeback, there must not be a '!'. This is
4312 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004313 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004314 return Error(Operands[3]->getStartLoc(),
4315 "writeback operator '!' not allowed when base register "
4316 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004317
4318 break;
4319 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004320 case ARM::t2LDMIA_UPD: {
4321 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4322 return Error(Operands[4]->getStartLoc(),
4323 "writeback operator '!' not allowed when base register "
4324 "in register list");
4325 break;
4326 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004327 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004328 bool listContainsBase;
4329 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4330 return Error(Operands[2]->getStartLoc(),
4331 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004332 break;
4333 }
4334 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004335 bool listContainsBase;
4336 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4337 return Error(Operands[2]->getStartLoc(),
4338 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004339 break;
4340 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004341 case ARM::tSTMIA_UPD: {
4342 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004343 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004344 return Error(Operands[4]->getStartLoc(),
4345 "registers must be in range r0-r7");
4346 break;
4347 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004348 }
4349
4350 return false;
4351}
4352
Jim Grosbachf8fce712011-08-11 17:35:48 +00004353void ARMAsmParser::
4354processInstruction(MCInst &Inst,
4355 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4356 switch (Inst.getOpcode()) {
4357 case ARM::LDMIA_UPD:
4358 // If this is a load of a single register via a 'pop', then we should use
4359 // a post-indexed LDR instruction instead, per the ARM ARM.
4360 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4361 Inst.getNumOperands() == 5) {
4362 MCInst TmpInst;
4363 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4364 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4365 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4366 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4367 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4368 TmpInst.addOperand(MCOperand::CreateImm(4));
4369 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4370 TmpInst.addOperand(Inst.getOperand(3));
4371 Inst = TmpInst;
4372 }
4373 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004374 case ARM::STMDB_UPD:
4375 // If this is a store of a single register via a 'push', then we should use
4376 // a pre-indexed STR instruction instead, per the ARM ARM.
4377 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4378 Inst.getNumOperands() == 5) {
4379 MCInst TmpInst;
4380 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4381 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4382 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4383 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4384 TmpInst.addOperand(MCOperand::CreateImm(-4));
4385 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4386 TmpInst.addOperand(Inst.getOperand(3));
4387 Inst = TmpInst;
4388 }
4389 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004390 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004391 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4392 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4393 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4394 // to encoding T1 if <Rd> is omitted."
4395 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004396 Inst.setOpcode(ARM::tADDi3);
4397 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004398 case ARM::tSUBi8:
4399 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4400 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4401 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4402 // to encoding T1 if <Rd> is omitted."
4403 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4404 Inst.setOpcode(ARM::tSUBi3);
4405 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004406 case ARM::tB:
4407 // A Thumb conditional branch outside of an IT block is a tBcc.
4408 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4409 Inst.setOpcode(ARM::tBcc);
4410 break;
4411 case ARM::t2B:
4412 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4413 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4414 Inst.setOpcode(ARM::t2Bcc);
4415 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004416 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004417 // If the conditional is AL or we're in an IT block, we really want t2B.
4418 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004419 Inst.setOpcode(ARM::t2B);
4420 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004421 case ARM::tBcc:
4422 // If the conditional is AL, we really want tB.
4423 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4424 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004425 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004426 case ARM::tLDMIA: {
4427 // If the register list contains any high registers, or if the writeback
4428 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4429 // instead if we're in Thumb2. Otherwise, this should have generated
4430 // an error in validateInstruction().
4431 unsigned Rn = Inst.getOperand(0).getReg();
4432 bool hasWritebackToken =
4433 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4434 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4435 bool listContainsBase;
4436 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4437 (!listContainsBase && !hasWritebackToken) ||
4438 (listContainsBase && hasWritebackToken)) {
4439 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4440 assert (isThumbTwo());
4441 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4442 // If we're switching to the updating version, we need to insert
4443 // the writeback tied operand.
4444 if (hasWritebackToken)
4445 Inst.insert(Inst.begin(),
4446 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4447 }
4448 break;
4449 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004450 case ARM::tSTMIA_UPD: {
4451 // If the register list contains any high registers, we need to use
4452 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4453 // should have generated an error in validateInstruction().
4454 unsigned Rn = Inst.getOperand(0).getReg();
4455 bool listContainsBase;
4456 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4457 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4458 assert (isThumbTwo());
4459 Inst.setOpcode(ARM::t2STMIA_UPD);
4460 }
4461 break;
4462 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004463 case ARM::t2MOVi: {
4464 // If we can use the 16-bit encoding and the user didn't explicitly
4465 // request the 32-bit variant, transform it here.
4466 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4467 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004468 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4469 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4470 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004471 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4472 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4473 // The operands aren't in the same order for tMOVi8...
4474 MCInst TmpInst;
4475 TmpInst.setOpcode(ARM::tMOVi8);
4476 TmpInst.addOperand(Inst.getOperand(0));
4477 TmpInst.addOperand(Inst.getOperand(4));
4478 TmpInst.addOperand(Inst.getOperand(1));
4479 TmpInst.addOperand(Inst.getOperand(2));
4480 TmpInst.addOperand(Inst.getOperand(3));
4481 Inst = TmpInst;
4482 }
4483 break;
4484 }
4485 case ARM::t2MOVr: {
4486 // If we can use the 16-bit encoding and the user didn't explicitly
4487 // request the 32-bit variant, transform it here.
4488 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4489 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4490 Inst.getOperand(2).getImm() == ARMCC::AL &&
4491 Inst.getOperand(4).getReg() == ARM::CPSR &&
4492 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4493 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4494 // The operands aren't the same for tMOV[S]r... (no cc_out)
4495 MCInst TmpInst;
4496 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4497 TmpInst.addOperand(Inst.getOperand(0));
4498 TmpInst.addOperand(Inst.getOperand(1));
4499 TmpInst.addOperand(Inst.getOperand(2));
4500 TmpInst.addOperand(Inst.getOperand(3));
4501 Inst = TmpInst;
4502 }
4503 break;
4504 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004505 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004506 case ARM::t2SXTB:
4507 case ARM::t2UXTH:
4508 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004509 // If we can use the 16-bit encoding and the user didn't explicitly
4510 // request the 32-bit variant, transform it here.
4511 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4512 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4513 Inst.getOperand(2).getImm() == 0 &&
4514 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4515 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004516 unsigned NewOpc;
4517 switch (Inst.getOpcode()) {
4518 default: llvm_unreachable("Illegal opcode!");
4519 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4520 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4521 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4522 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4523 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004524 // The operands aren't the same for thumb1 (no rotate operand).
4525 MCInst TmpInst;
4526 TmpInst.setOpcode(NewOpc);
4527 TmpInst.addOperand(Inst.getOperand(0));
4528 TmpInst.addOperand(Inst.getOperand(1));
4529 TmpInst.addOperand(Inst.getOperand(3));
4530 TmpInst.addOperand(Inst.getOperand(4));
4531 Inst = TmpInst;
4532 }
4533 break;
4534 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004535 case ARM::t2IT: {
4536 // The mask bits for all but the first condition are represented as
4537 // the low bit of the condition code value implies 't'. We currently
4538 // always have 1 implies 't', so XOR toggle the bits if the low bit
4539 // of the condition code is zero. The encoding also expects the low
4540 // bit of the condition to be encoded as bit 4 of the mask operand,
4541 // so mask that in if needed
4542 MCOperand &MO = Inst.getOperand(1);
4543 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004544 unsigned OrigMask = Mask;
4545 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004546 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004547 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4548 for (unsigned i = 3; i != TZ; --i)
4549 Mask ^= 1 << i;
4550 } else
4551 Mask |= 0x10;
4552 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004553
4554 // Set up the IT block state according to the IT instruction we just
4555 // matched.
4556 assert(!inITBlock() && "nested IT blocks?!");
4557 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4558 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4559 ITState.CurPosition = 0;
4560 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004561 break;
4562 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004563 }
4564}
4565
Jim Grosbach47a0d522011-08-16 20:45:50 +00004566unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4567 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4568 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004569 unsigned Opc = Inst.getOpcode();
4570 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004571 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4572 assert(MCID.hasOptionalDef() &&
4573 "optionally flag setting instruction missing optional def operand");
4574 assert(MCID.NumOperands == Inst.getNumOperands() &&
4575 "operand count mismatch!");
4576 // Find the optional-def operand (cc_out).
4577 unsigned OpNo;
4578 for (OpNo = 0;
4579 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4580 ++OpNo)
4581 ;
4582 // If we're parsing Thumb1, reject it completely.
4583 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4584 return Match_MnemonicFail;
4585 // If we're parsing Thumb2, which form is legal depends on whether we're
4586 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004587 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4588 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004589 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004590 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4591 inITBlock())
4592 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004593 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004594 // Some high-register supporting Thumb1 encodings only allow both registers
4595 // to be from r0-r7 when in Thumb2.
4596 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4597 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4598 isARMLowRegister(Inst.getOperand(2).getReg()))
4599 return Match_RequiresThumb2;
4600 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004601 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004602 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4603 isARMLowRegister(Inst.getOperand(1).getReg()))
4604 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004605 return Match_Success;
4606}
4607
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004608bool ARMAsmParser::
4609MatchAndEmitInstruction(SMLoc IDLoc,
4610 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4611 MCStreamer &Out) {
4612 MCInst Inst;
4613 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004614 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004615 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004616 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004617 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004618 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004619 // Context sensitive operand constraints aren't handled by the matcher,
4620 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004621 if (validateInstruction(Inst, Operands)) {
4622 // Still progress the IT block, otherwise one wrong condition causes
4623 // nasty cascading errors.
4624 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004625 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004626 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004627
Jim Grosbachf8fce712011-08-11 17:35:48 +00004628 // Some instructions need post-processing to, for example, tweak which
4629 // encoding is selected.
4630 processInstruction(Inst, Operands);
4631
Jim Grosbacha1109882011-09-02 23:22:08 +00004632 // Only move forward at the very end so that everything in validate
4633 // and process gets a consistent answer about whether we're in an IT
4634 // block.
4635 forwardITPosition();
4636
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004637 Out.EmitInstruction(Inst);
4638 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004639 case Match_MissingFeature:
4640 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4641 return true;
4642 case Match_InvalidOperand: {
4643 SMLoc ErrorLoc = IDLoc;
4644 if (ErrorInfo != ~0U) {
4645 if (ErrorInfo >= Operands.size())
4646 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004647
Chris Lattnere73d4f82010-10-28 21:41:58 +00004648 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4649 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4650 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004651
Chris Lattnere73d4f82010-10-28 21:41:58 +00004652 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004653 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004654 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004655 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004656 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004657 // The converter function will have already emited a diagnostic.
4658 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004659 case Match_RequiresNotITBlock:
4660 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004661 case Match_RequiresITBlock:
4662 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004663 case Match_RequiresV6:
4664 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4665 case Match_RequiresThumb2:
4666 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004667 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004668
Eric Christopherc223e2b2010-10-29 09:26:59 +00004669 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004670 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004671}
4672
Jim Grosbach1355cf12011-07-26 17:10:22 +00004673/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004674bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4675 StringRef IDVal = DirectiveID.getIdentifier();
4676 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004677 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004678 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004679 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004680 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004681 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004682 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004683 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004684 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004685 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004686 return true;
4687}
4688
Jim Grosbach1355cf12011-07-26 17:10:22 +00004689/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004690/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004691bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004692 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4693 for (;;) {
4694 const MCExpr *Value;
4695 if (getParser().ParseExpression(Value))
4696 return true;
4697
Chris Lattneraaec2052010-01-19 19:46:13 +00004698 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004699
4700 if (getLexer().is(AsmToken::EndOfStatement))
4701 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004702
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004703 // FIXME: Improve diagnostic.
4704 if (getLexer().isNot(AsmToken::Comma))
4705 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004706 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004707 }
4708 }
4709
Sean Callananb9a25b72010-01-19 20:27:46 +00004710 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004711 return false;
4712}
4713
Jim Grosbach1355cf12011-07-26 17:10:22 +00004714/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004715/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004716bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004717 if (getLexer().isNot(AsmToken::EndOfStatement))
4718 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004719 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004720
4721 // TODO: set thumb mode
4722 // TODO: tell the MC streamer the mode
4723 // getParser().getStreamer().Emit???();
4724 return false;
4725}
4726
Jim Grosbach1355cf12011-07-26 17:10:22 +00004727/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004728/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004729bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004730 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4731 bool isMachO = MAI.hasSubsectionsViaSymbols();
4732 StringRef Name;
4733
4734 // Darwin asm has function name after .thumb_func direction
4735 // ELF doesn't
4736 if (isMachO) {
4737 const AsmToken &Tok = Parser.getTok();
4738 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4739 return Error(L, "unexpected token in .thumb_func directive");
4740 Name = Tok.getString();
4741 Parser.Lex(); // Consume the identifier token.
4742 }
4743
Kevin Enderby515d5092009-10-15 20:48:48 +00004744 if (getLexer().isNot(AsmToken::EndOfStatement))
4745 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004746 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004747
Rafael Espindola64695402011-05-16 16:17:21 +00004748 // FIXME: assuming function name will be the line following .thumb_func
4749 if (!isMachO) {
4750 Name = Parser.getTok().getString();
4751 }
4752
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004753 // Mark symbol as a thumb symbol.
4754 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4755 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004756 return false;
4757}
4758
Jim Grosbach1355cf12011-07-26 17:10:22 +00004759/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004760/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004761bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004762 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004763 if (Tok.isNot(AsmToken::Identifier))
4764 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004765 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004766 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004767 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004768 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004769 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004770 else
4771 return Error(L, "unrecognized syntax mode in .syntax directive");
4772
4773 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004774 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004775 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004776
4777 // TODO tell the MC streamer the mode
4778 // getParser().getStreamer().Emit???();
4779 return false;
4780}
4781
Jim Grosbach1355cf12011-07-26 17:10:22 +00004782/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004783/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004784bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004785 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004786 if (Tok.isNot(AsmToken::Integer))
4787 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004788 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004789 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004790 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004791 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004792 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004793 else
4794 return Error(L, "invalid operand to .code directive");
4795
4796 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004797 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004798 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004799
Evan Cheng32869202011-07-08 22:36:29 +00004800 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004801 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004802 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004803 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004804 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004805 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004806 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004807 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004808 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004809
Kevin Enderby515d5092009-10-15 20:48:48 +00004810 return false;
4811}
4812
Sean Callanan90b70972010-04-07 20:29:34 +00004813extern "C" void LLVMInitializeARMAsmLexer();
4814
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004815/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004816extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004817 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4818 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004819 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004820}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004821
Chris Lattner0692ee62010-09-06 19:11:01 +00004822#define GET_REGISTER_MATCHER
4823#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004824#include "ARMGenAsmMatcher.inc"